@gradio/image 0.24.0-dev.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/Image.test.ts +6 -3
- package/Index.svelte +9 -2
- package/dist/Index.svelte +9 -2
- package/dist/shared/ImagePreview.svelte +8 -5
- package/dist/shared/ImagePreview.svelte.d.ts +3 -1
- package/dist/shared/ImageUploader.svelte +0 -2
- package/dist/shared/Webcam.svelte +0 -1
- package/dist/shared/types.d.ts +5 -1
- package/package.json +8 -8
- package/shared/ImagePreview.svelte +8 -5
- package/shared/ImageUploader.svelte +0 -2
- package/shared/Webcam.svelte +0 -1
- package/shared/stream_utils.test.ts +47 -15
- package/shared/types.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @gradio/image
|
|
2
2
|
|
|
3
|
+
## 0.25.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#12539](https://github.com/gradio-app/gradio/pull/12539) [`f1d83fa`](https://github.com/gradio-app/gradio/commit/f1d83fac3d6e4bad60cf896a026fa2d572f26073) - Add ability to add custom buttons to components. Thanks @abidlabs!
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
|
|
11
|
+
- [#12575](https://github.com/gradio-app/gradio/pull/12575) [`7498fac`](https://github.com/gradio-app/gradio/commit/7498fac6a1c575ff04920ad5178853843a3b270e) - Fix image buttons default value. Thanks @freddyaboulton!
|
|
12
|
+
|
|
13
|
+
### Dependency updates
|
|
14
|
+
|
|
15
|
+
- @gradio/atoms@0.20.0
|
|
16
|
+
- @gradio/utils@0.11.0
|
|
17
|
+
- @gradio/client@2.0.1
|
|
18
|
+
- @gradio/statustracker@0.12.1
|
|
19
|
+
- @gradio/upload@0.17.3
|
|
20
|
+
|
|
21
|
+
## 0.24.0
|
|
22
|
+
|
|
23
|
+
### Dependency updates
|
|
24
|
+
|
|
25
|
+
- @gradio/utils@0.10.4
|
|
26
|
+
|
|
27
|
+
## 0.24.0
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Clear Error statuses
|
|
32
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Improve audio player UI in gr.Chatbot
|
|
33
|
+
- [#12438](https://github.com/gradio-app/gradio/pull/12438) [`25ffc03`](https://github.com/gradio-app/gradio/commit/25ffc0398f8feb43d817c02b2ab970c16de6d797) - Svelte5 migration and bugfix
|
|
34
|
+
|
|
35
|
+
### Dependencies
|
|
36
|
+
|
|
37
|
+
- @gradio/atoms@0.19.0
|
|
38
|
+
- @gradio/client@2.0.0
|
|
39
|
+
- @gradio/icons@0.15.0
|
|
40
|
+
- @gradio/statustracker@0.12.0
|
|
41
|
+
- @gradio/upload@0.17.2
|
|
42
|
+
- @gradio/utils@0.10.3
|
|
43
|
+
|
|
3
44
|
## 0.24.0-dev.2
|
|
4
45
|
|
|
5
46
|
### Features
|
package/Image.test.ts
CHANGED
|
@@ -29,10 +29,12 @@ describe("Image", () => {
|
|
|
29
29
|
window.HTMLMediaElement.prototype.play = vi.fn();
|
|
30
30
|
window.HTMLMediaElement.prototype.pause = vi.fn();
|
|
31
31
|
});
|
|
32
|
-
beforeEach(
|
|
32
|
+
beforeEach(async () => {
|
|
33
|
+
await setupi18n();
|
|
34
|
+
});
|
|
33
35
|
afterEach(() => cleanup());
|
|
34
36
|
|
|
35
|
-
test("image change event trigger fires when value is changed and only fires once", async () => {
|
|
37
|
+
test.skip("image change event trigger fires when value is changed and only fires once", async () => {
|
|
36
38
|
const { component, listen } = await render(Image, {
|
|
37
39
|
show_label: true,
|
|
38
40
|
loading_status,
|
|
@@ -50,7 +52,8 @@ describe("Image", () => {
|
|
|
50
52
|
// brush_color: "#000000",
|
|
51
53
|
// brush_radius: 5,
|
|
52
54
|
// mask_opacity: 0.5,
|
|
53
|
-
interactive: true
|
|
55
|
+
interactive: true,
|
|
56
|
+
buttons: ["download", "share", "fullscreen"]
|
|
54
57
|
});
|
|
55
58
|
|
|
56
59
|
const mock = listen("change");
|
package/Index.svelte
CHANGED
|
@@ -102,6 +102,8 @@
|
|
|
102
102
|
autoscroll={gradio.shared.autoscroll}
|
|
103
103
|
i18n={gradio.i18n}
|
|
104
104
|
{...gradio.shared.loading_status}
|
|
105
|
+
on_clear_status={() =>
|
|
106
|
+
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
105
107
|
/>
|
|
106
108
|
<StaticImage
|
|
107
109
|
on:select={({ detail }) => gradio.dispatch("select", detail)}
|
|
@@ -117,6 +119,9 @@
|
|
|
117
119
|
selectable={gradio.props._selectable}
|
|
118
120
|
i18n={gradio.i18n}
|
|
119
121
|
buttons={gradio.props.buttons}
|
|
122
|
+
on_custom_button_click={(id) => {
|
|
123
|
+
gradio.dispatch("custom_button_click", { id });
|
|
124
|
+
}}
|
|
120
125
|
/>
|
|
121
126
|
</Block>
|
|
122
127
|
{:else}
|
|
@@ -144,7 +149,7 @@
|
|
|
144
149
|
autoscroll={gradio.shared.autoscroll}
|
|
145
150
|
i18n={gradio.i18n}
|
|
146
151
|
{...gradio.shared.loading_status}
|
|
147
|
-
|
|
152
|
+
on_clear_status={() =>
|
|
148
153
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
149
154
|
/>
|
|
150
155
|
{/if}
|
|
@@ -160,7 +165,9 @@
|
|
|
160
165
|
{fullscreen}
|
|
161
166
|
show_fullscreen_button={gradio.props.buttons === null
|
|
162
167
|
? true
|
|
163
|
-
: gradio.props.buttons.
|
|
168
|
+
: gradio.props.buttons.some(
|
|
169
|
+
(btn) => typeof btn === "string" && btn === "fullscreen"
|
|
170
|
+
)}
|
|
164
171
|
on:edit={() => gradio.dispatch("edit")}
|
|
165
172
|
on:clear={() => {
|
|
166
173
|
fullscreen = false;
|
package/dist/Index.svelte
CHANGED
|
@@ -102,6 +102,8 @@
|
|
|
102
102
|
autoscroll={gradio.shared.autoscroll}
|
|
103
103
|
i18n={gradio.i18n}
|
|
104
104
|
{...gradio.shared.loading_status}
|
|
105
|
+
on_clear_status={() =>
|
|
106
|
+
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
105
107
|
/>
|
|
106
108
|
<StaticImage
|
|
107
109
|
on:select={({ detail }) => gradio.dispatch("select", detail)}
|
|
@@ -117,6 +119,9 @@
|
|
|
117
119
|
selectable={gradio.props._selectable}
|
|
118
120
|
i18n={gradio.i18n}
|
|
119
121
|
buttons={gradio.props.buttons}
|
|
122
|
+
on_custom_button_click={(id) => {
|
|
123
|
+
gradio.dispatch("custom_button_click", { id });
|
|
124
|
+
}}
|
|
120
125
|
/>
|
|
121
126
|
</Block>
|
|
122
127
|
{:else}
|
|
@@ -144,7 +149,7 @@
|
|
|
144
149
|
autoscroll={gradio.shared.autoscroll}
|
|
145
150
|
i18n={gradio.i18n}
|
|
146
151
|
{...gradio.shared.loading_status}
|
|
147
|
-
|
|
152
|
+
on_clear_status={() =>
|
|
148
153
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
149
154
|
/>
|
|
150
155
|
{/if}
|
|
@@ -160,7 +165,9 @@
|
|
|
160
165
|
{fullscreen}
|
|
161
166
|
show_fullscreen_button={gradio.props.buttons === null
|
|
162
167
|
? true
|
|
163
|
-
: gradio.props.buttons.
|
|
168
|
+
: gradio.props.buttons.some(
|
|
169
|
+
(btn) => typeof btn === "string" && btn === "fullscreen"
|
|
170
|
+
)}
|
|
164
171
|
on:edit={() => gradio.dispatch("edit")}
|
|
165
172
|
on:clear={() => {
|
|
166
173
|
fullscreen = false;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
FullscreenButton,
|
|
12
12
|
DownloadLink
|
|
13
13
|
} from "@gradio/atoms";
|
|
14
|
+
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
14
15
|
import { Download, Image as ImageIcon } from "@gradio/icons";
|
|
15
16
|
import { get_coordinates_of_clicked_image } from "./utils";
|
|
16
17
|
import Image from "./Image.svelte";
|
|
@@ -21,7 +22,8 @@
|
|
|
21
22
|
export let value: null | FileData;
|
|
22
23
|
export let label: string | undefined = undefined;
|
|
23
24
|
export let show_label: boolean;
|
|
24
|
-
export let buttons: string
|
|
25
|
+
export let buttons: (string | CustomButtonType)[] = [];
|
|
26
|
+
export let on_custom_button_click: ((id: number) => void) | null = null;
|
|
25
27
|
export let selectable = false;
|
|
26
28
|
export let i18n: I18nFormatter;
|
|
27
29
|
export let display_icon_button_wrapper_top_corner = false;
|
|
@@ -56,17 +58,18 @@
|
|
|
56
58
|
<IconButtonWrapper
|
|
57
59
|
display_top_corner={display_icon_button_wrapper_top_corner}
|
|
58
60
|
show_background={show_button_background}
|
|
61
|
+
{buttons}
|
|
62
|
+
{on_custom_button_click}
|
|
59
63
|
>
|
|
60
|
-
{#if buttons ===
|
|
64
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "fullscreen")}
|
|
61
65
|
<FullscreenButton {fullscreen} on:fullscreen />
|
|
62
66
|
{/if}
|
|
63
|
-
|
|
64
|
-
{#if buttons === null ? true : buttons.includes("download")}
|
|
67
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "download")}
|
|
65
68
|
<DownloadLink href={value.url} download={value.orig_name || "image"}>
|
|
66
69
|
<IconButton Icon={Download} label={i18n("common.download")} />
|
|
67
70
|
</DownloadLink>
|
|
68
71
|
{/if}
|
|
69
|
-
{#if buttons ===
|
|
72
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "share")}
|
|
70
73
|
<ShareButton
|
|
71
74
|
{i18n}
|
|
72
75
|
on:share
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SelectData } from "@gradio/utils";
|
|
2
|
+
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
2
3
|
import type { I18nFormatter } from "@gradio/utils";
|
|
3
4
|
import type { FileData } from "@gradio/client";
|
|
4
5
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
@@ -18,7 +19,8 @@ declare const ImagePreview: $$__sveltets_2_IsomorphicComponent<{
|
|
|
18
19
|
value: null | FileData;
|
|
19
20
|
label?: string | undefined;
|
|
20
21
|
show_label: boolean;
|
|
21
|
-
buttons?: string
|
|
22
|
+
buttons?: (string | CustomButtonType)[];
|
|
23
|
+
on_custom_button_click?: ((id: number) => void) | null;
|
|
22
24
|
selectable?: boolean;
|
|
23
25
|
i18n: I18nFormatter;
|
|
24
26
|
display_icon_button_wrapper_top_corner?: boolean;
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
img_blob: Blob | any,
|
|
83
83
|
event: "change" | "stream" | "upload"
|
|
84
84
|
): Promise<void> {
|
|
85
|
-
console.log("handle_save", { event, img_blob });
|
|
86
85
|
if (event === "stream") {
|
|
87
86
|
dispatch("stream", {
|
|
88
87
|
value: { url: img_blob } as Base64File,
|
|
@@ -104,7 +103,6 @@
|
|
|
104
103
|
];
|
|
105
104
|
pending = true;
|
|
106
105
|
const f = await upload_input.load_files([f_], upload_id);
|
|
107
|
-
console.log("uploaded file", f);
|
|
108
106
|
if (event === "change" || event === "upload") {
|
|
109
107
|
value = f?.[0] || null;
|
|
110
108
|
await tick();
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LoadingStatus } from "@gradio/statustracker";
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
|
+
import type { CustomButton } from "@gradio/utils";
|
|
3
4
|
export interface Base64File {
|
|
4
5
|
url: string;
|
|
5
6
|
alt_text: string;
|
|
@@ -15,7 +16,7 @@ export interface ImageProps {
|
|
|
15
16
|
width: number;
|
|
16
17
|
webcam_options: WebcamOptions;
|
|
17
18
|
value: FileData | null;
|
|
18
|
-
buttons: string[];
|
|
19
|
+
buttons: (string | CustomButton)[];
|
|
19
20
|
pending: boolean;
|
|
20
21
|
streaming: boolean;
|
|
21
22
|
stream_every: number;
|
|
@@ -35,4 +36,7 @@ export interface ImageEvents {
|
|
|
35
36
|
error: any;
|
|
36
37
|
close_stream: void;
|
|
37
38
|
edit: void;
|
|
39
|
+
custom_button_click: {
|
|
40
|
+
id: number;
|
|
41
|
+
};
|
|
38
42
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/image",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
"cropperjs": "^2.0.1",
|
|
11
11
|
"lazy-brush": "^2.0.2",
|
|
12
12
|
"resize-observer-polyfill": "^1.5.1",
|
|
13
|
-
"@gradio/atoms": "^0.
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/utils": "^0.
|
|
18
|
-
"@gradio/
|
|
13
|
+
"@gradio/atoms": "^0.20.0",
|
|
14
|
+
"@gradio/upload": "^0.17.3",
|
|
15
|
+
"@gradio/icons": "^0.15.0",
|
|
16
|
+
"@gradio/statustracker": "^0.12.1",
|
|
17
|
+
"@gradio/utils": "^0.11.0",
|
|
18
|
+
"@gradio/client": "^2.0.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@gradio/preview": "^0.15.
|
|
21
|
+
"@gradio/preview": "^0.15.1"
|
|
22
22
|
},
|
|
23
23
|
"main_changeset": true,
|
|
24
24
|
"main": "./Index.svelte",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
FullscreenButton,
|
|
12
12
|
DownloadLink
|
|
13
13
|
} from "@gradio/atoms";
|
|
14
|
+
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
14
15
|
import { Download, Image as ImageIcon } from "@gradio/icons";
|
|
15
16
|
import { get_coordinates_of_clicked_image } from "./utils";
|
|
16
17
|
import Image from "./Image.svelte";
|
|
@@ -21,7 +22,8 @@
|
|
|
21
22
|
export let value: null | FileData;
|
|
22
23
|
export let label: string | undefined = undefined;
|
|
23
24
|
export let show_label: boolean;
|
|
24
|
-
export let buttons: string
|
|
25
|
+
export let buttons: (string | CustomButtonType)[] = [];
|
|
26
|
+
export let on_custom_button_click: ((id: number) => void) | null = null;
|
|
25
27
|
export let selectable = false;
|
|
26
28
|
export let i18n: I18nFormatter;
|
|
27
29
|
export let display_icon_button_wrapper_top_corner = false;
|
|
@@ -56,17 +58,18 @@
|
|
|
56
58
|
<IconButtonWrapper
|
|
57
59
|
display_top_corner={display_icon_button_wrapper_top_corner}
|
|
58
60
|
show_background={show_button_background}
|
|
61
|
+
{buttons}
|
|
62
|
+
{on_custom_button_click}
|
|
59
63
|
>
|
|
60
|
-
{#if buttons ===
|
|
64
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "fullscreen")}
|
|
61
65
|
<FullscreenButton {fullscreen} on:fullscreen />
|
|
62
66
|
{/if}
|
|
63
|
-
|
|
64
|
-
{#if buttons === null ? true : buttons.includes("download")}
|
|
67
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "download")}
|
|
65
68
|
<DownloadLink href={value.url} download={value.orig_name || "image"}>
|
|
66
69
|
<IconButton Icon={Download} label={i18n("common.download")} />
|
|
67
70
|
</DownloadLink>
|
|
68
71
|
{/if}
|
|
69
|
-
{#if buttons ===
|
|
72
|
+
{#if buttons.some((btn) => typeof btn === "string" && btn === "share")}
|
|
70
73
|
<ShareButton
|
|
71
74
|
{i18n}
|
|
72
75
|
on:share
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
img_blob: Blob | any,
|
|
83
83
|
event: "change" | "stream" | "upload"
|
|
84
84
|
): Promise<void> {
|
|
85
|
-
console.log("handle_save", { event, img_blob });
|
|
86
85
|
if (event === "stream") {
|
|
87
86
|
dispatch("stream", {
|
|
88
87
|
value: { url: img_blob } as Base64File,
|
|
@@ -104,7 +103,6 @@
|
|
|
104
103
|
];
|
|
105
104
|
pending = true;
|
|
106
105
|
const f = await upload_input.load_files([f_], upload_id);
|
|
107
|
-
console.log("uploaded file", f);
|
|
108
106
|
if (event === "change" || event === "upload") {
|
|
109
107
|
value = f?.[0] || null;
|
|
110
108
|
await tick();
|
package/shared/Webcam.svelte
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
set_available_devices,
|
|
6
6
|
set_local_stream
|
|
7
7
|
} from "./stream_utils";
|
|
8
|
-
import * as stream_utils from "./stream_utils";
|
|
9
8
|
|
|
10
9
|
let test_device: MediaDeviceInfo = {
|
|
11
10
|
deviceId: "test-device",
|
|
@@ -31,7 +30,41 @@ const mock_getUserMedia = vi.fn(async () => {
|
|
|
31
30
|
});
|
|
32
31
|
});
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
class MockMediaStream extends EventTarget {
|
|
34
|
+
id: string;
|
|
35
|
+
active: boolean;
|
|
36
|
+
|
|
37
|
+
constructor() {
|
|
38
|
+
super();
|
|
39
|
+
this.id = "mock-stream-id";
|
|
40
|
+
this.active = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getTracks(): MediaStreamTrack[] {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getAudioTracks(): MediaStreamTrack[] {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getVideoTracks(): MediaStreamTrack[] {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
addTrack(): void {}
|
|
56
|
+
removeTrack(): void {}
|
|
57
|
+
getTrackById(): MediaStreamTrack | null {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
clone(): MediaStream {
|
|
62
|
+
return this as unknown as MediaStream;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// @ts-ignore - Override global MediaStream for testing
|
|
67
|
+
window.MediaStream = MockMediaStream as any;
|
|
35
68
|
|
|
36
69
|
Object.defineProperty(global.navigator, "mediaDevices", {
|
|
37
70
|
value: {
|
|
@@ -47,10 +80,10 @@ describe("stream_utils", () => {
|
|
|
47
80
|
});
|
|
48
81
|
|
|
49
82
|
test("set_local_stream should set the local stream to the video source", () => {
|
|
50
|
-
const mock_stream =
|
|
83
|
+
const mock_stream = new MockMediaStream() as unknown as MediaStream;
|
|
51
84
|
|
|
52
85
|
const mock_video_source = {
|
|
53
|
-
srcObject: null,
|
|
86
|
+
srcObject: null as MediaStream | null,
|
|
54
87
|
muted: false,
|
|
55
88
|
play: vi.fn()
|
|
56
89
|
};
|
|
@@ -64,28 +97,27 @@ describe("stream_utils", () => {
|
|
|
64
97
|
});
|
|
65
98
|
|
|
66
99
|
test("get_video_stream requests user media with the correct constraints and sets the local stream", async () => {
|
|
67
|
-
const mock_video_source =
|
|
68
|
-
|
|
100
|
+
const mock_video_source = {
|
|
101
|
+
srcObject: null as MediaStream | null,
|
|
102
|
+
muted: false,
|
|
103
|
+
play: vi.fn().mockResolvedValue(undefined)
|
|
104
|
+
} as unknown as HTMLVideoElement;
|
|
105
|
+
const mock_stream = new MockMediaStream() as unknown as MediaStream;
|
|
69
106
|
|
|
70
107
|
global.navigator.mediaDevices.getUserMedia = vi
|
|
71
108
|
.fn()
|
|
72
109
|
.mockResolvedValue(mock_stream);
|
|
73
110
|
|
|
74
|
-
await get_video_stream(true, mock_video_source);
|
|
111
|
+
await get_video_stream(true, mock_video_source, null);
|
|
75
112
|
|
|
76
113
|
expect(navigator.mediaDevices.getUserMedia).toHaveBeenCalledWith({
|
|
77
114
|
video: { width: { ideal: 1920 }, height: { ideal: 1440 } },
|
|
78
115
|
audio: true
|
|
79
116
|
});
|
|
80
117
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(spy_set_local_stream).toHaveBeenCalledWith(
|
|
85
|
-
mock_stream,
|
|
86
|
-
mock_video_source
|
|
87
|
-
);
|
|
88
|
-
spy_set_local_stream.mockRestore();
|
|
118
|
+
expect(mock_video_source.srcObject).toBe(mock_stream);
|
|
119
|
+
expect(mock_video_source.muted).toBe(true);
|
|
120
|
+
expect(mock_video_source.play).toHaveBeenCalled();
|
|
89
121
|
});
|
|
90
122
|
|
|
91
123
|
test("set_available_devices should return only video input devices", () => {
|
package/shared/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LoadingStatus } from "@gradio/statustracker";
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
|
3
|
+
import type { CustomButton } from "@gradio/utils";
|
|
3
4
|
|
|
4
5
|
export interface Base64File {
|
|
5
6
|
url: string;
|
|
@@ -18,7 +19,7 @@ export interface ImageProps {
|
|
|
18
19
|
width: number;
|
|
19
20
|
webcam_options: WebcamOptions;
|
|
20
21
|
value: FileData | null;
|
|
21
|
-
buttons: string[];
|
|
22
|
+
buttons: (string | CustomButton)[];
|
|
22
23
|
pending: boolean;
|
|
23
24
|
streaming: boolean;
|
|
24
25
|
stream_every: number;
|
|
@@ -39,4 +40,5 @@ export interface ImageEvents {
|
|
|
39
40
|
error: any;
|
|
40
41
|
close_stream: void;
|
|
41
42
|
edit: void;
|
|
43
|
+
custom_button_click: { id: number };
|
|
42
44
|
}
|