@gradio/image 0.19.0 → 0.20.1

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # @gradio/image
2
2
 
3
+ ## 0.20.1
4
+
5
+ ### Fixes
6
+
7
+ - [#10327](https://github.com/gradio-app/gradio/pull/10327) [`e0cb47f`](https://github.com/gradio-app/gradio/commit/e0cb47f0c5040049fb942a381c0335de4bf77d67) - Fix webcam. Thanks @Col0ring!
8
+
9
+ ### Dependency updates
10
+
11
+ - @gradio/atoms@0.13.1
12
+ - @gradio/statustracker@0.10.1
13
+ - @gradio/client@1.10.0
14
+ - @gradio/icons@0.10.0
15
+ - @gradio/upload@0.14.5
16
+
17
+ ## 0.20.0
18
+
19
+ ### Features
20
+
21
+ - [#10192](https://github.com/gradio-app/gradio/pull/10192) [`4fc7fb7`](https://github.com/gradio-app/gradio/commit/4fc7fb777c42af537e4af612423fa44029657d41) - Ensure components can be remounted with their previous data. Thanks @pngwn!
22
+
23
+ ### Fixes
24
+
25
+ - [#10269](https://github.com/gradio-app/gradio/pull/10269) [`890eaa3`](https://github.com/gradio-app/gradio/commit/890eaa3a9e53dab5bcb16c5d017ae0470109b8fb) - Allow displaying SVG images securely in `gr.Image` and `gr.Gallery` components. Thanks @abidlabs!
26
+
27
+ ### Dependency updates
28
+
29
+ - @gradio/atoms@0.13.0
30
+ - @gradio/utils@0.10.0
31
+ - @gradio/upload@0.14.4
32
+ - @gradio/client@1.9.0
33
+ - @gradio/icons@0.9.0
34
+ - @gradio/statustracker@0.10.0
35
+ - @gradio/wasm@0.16.0
36
+
3
37
  ## 0.19.0
4
38
 
5
39
  ### Features
@@ -31,9 +31,20 @@ let upload_input;
31
31
  export let uploading = false;
32
32
  export let active_source = null;
33
33
  export let webcam_constraints = void 0;
34
- function handle_upload({ detail }) {
34
+ async function handle_upload({
35
+ detail
36
+ }) {
35
37
  if (!streaming) {
36
- value = detail;
38
+ if (detail.path?.toLowerCase().endsWith(".svg") && detail.url) {
39
+ const response = await fetch(detail.url);
40
+ const svgContent = await response.text();
41
+ value = {
42
+ ...detail,
43
+ url: `data:image/svg+xml,${encodeURIComponent(svgContent)}`
44
+ };
45
+ } else {
46
+ value = detail;
47
+ }
37
48
  dispatch("upload");
38
49
  }
39
50
  }
@@ -1,4 +1,4 @@
1
- <script>import { createEventDispatcher, onMount } from "svelte";
1
+ <script>import { createEventDispatcher, onDestroy, onMount } from "svelte";
2
2
  import {
3
3
  Camera,
4
4
  Circle,
@@ -152,7 +152,7 @@ function take_recording() {
152
152
  }
153
153
  };
154
154
  ReaderObj.readAsDataURL(video_blob);
155
- } else {
155
+ } else if (typeof MediaRecorder !== "undefined") {
156
156
  dispatch("start_recording");
157
157
  recorded_blobs = [];
158
158
  let validMimeTypes = ["video/webm", "video/mp4"];
@@ -177,14 +177,18 @@ function take_recording() {
177
177
  recording = !recording;
178
178
  }
179
179
  let webcam_accessed = false;
180
- function record_video_or_photo() {
180
+ function record_video_or_photo({
181
+ destroy
182
+ } = {}) {
181
183
  if (mode === "image" && streaming) {
182
184
  recording = !recording;
183
185
  }
184
- if (mode === "image") {
185
- take_picture();
186
- } else {
187
- take_recording();
186
+ if (!destroy) {
187
+ if (mode === "image") {
188
+ take_picture();
189
+ } else {
190
+ take_recording();
191
+ }
188
192
  }
189
193
  if (!recording && stream) {
190
194
  dispatch("close_stream");
@@ -216,6 +220,12 @@ function handle_click_outside(event) {
216
220
  event.stopPropagation();
217
221
  options_open = false;
218
222
  }
223
+ onDestroy(() => {
224
+ if (typeof window === "undefined")
225
+ return;
226
+ record_video_or_photo({ destroy: true });
227
+ stream?.getTracks().forEach((track) => track.stop());
228
+ });
219
229
  </script>
220
230
 
221
231
  <div class="wrap">
@@ -243,7 +253,7 @@ function handle_click_outside(event) {
243
253
  {:else}
244
254
  <div class="button-wrap">
245
255
  <button
246
- on:click={record_video_or_photo}
256
+ on:click={() => record_video_or_photo()}
247
257
  aria-label={mode === "image" ? "capture photo" : "start recording"}
248
258
  >
249
259
  {#if mode === "video" || streaming}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/image",
3
- "version": "0.19.0",
3
+ "version": "0.20.1",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -10,13 +10,13 @@
10
10
  "cropperjs": "^1.5.12",
11
11
  "lazy-brush": "^1.0.1",
12
12
  "resize-observer-polyfill": "^1.5.1",
13
- "@gradio/atoms": "^0.12.0",
14
- "@gradio/client": "^1.8.0",
15
- "@gradio/icons": "^0.8.1",
16
- "@gradio/statustracker": "^0.9.7",
17
- "@gradio/upload": "^0.14.3",
18
- "@gradio/utils": "^0.9.0",
19
- "@gradio/wasm": "^0.15.0"
13
+ "@gradio/atoms": "^0.13.1",
14
+ "@gradio/icons": "^0.10.0",
15
+ "@gradio/client": "^1.10.0",
16
+ "@gradio/statustracker": "^0.10.1",
17
+ "@gradio/upload": "^0.14.5",
18
+ "@gradio/utils": "^0.10.0",
19
+ "@gradio/wasm": "^0.16.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@gradio/preview": "^0.13.0"
@@ -45,10 +45,20 @@
45
45
 
46
46
  export let webcam_constraints: { [key: string]: any } | undefined = undefined;
47
47
 
48
- function handle_upload({ detail }: CustomEvent<FileData>): void {
49
- // only trigger streaming event if streaming
48
+ async function handle_upload({
49
+ detail
50
+ }: CustomEvent<FileData>): Promise<void> {
50
51
  if (!streaming) {
51
- value = detail;
52
+ if (detail.path?.toLowerCase().endsWith(".svg") && detail.url) {
53
+ const response = await fetch(detail.url);
54
+ const svgContent = await response.text();
55
+ value = {
56
+ ...detail,
57
+ url: `data:image/svg+xml,${encodeURIComponent(svgContent)}`
58
+ };
59
+ } else {
60
+ value = detail;
61
+ }
52
62
  dispatch("upload");
53
63
  }
54
64
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { createEventDispatcher, onMount } from "svelte";
2
+ import { createEventDispatcher, onDestroy, onMount } from "svelte";
3
3
  import {
4
4
  Camera,
5
5
  Circle,
@@ -198,7 +198,7 @@
198
198
  }
199
199
  };
200
200
  ReaderObj.readAsDataURL(video_blob);
201
- } else {
201
+ } else if (typeof MediaRecorder !== "undefined") {
202
202
  dispatch("start_recording");
203
203
  recorded_blobs = [];
204
204
  let validMimeTypes = ["video/webm", "video/mp4"];
@@ -225,15 +225,21 @@
225
225
 
226
226
  let webcam_accessed = false;
227
227
 
228
- function record_video_or_photo(): void {
228
+ function record_video_or_photo({
229
+ destroy
230
+ }: { destroy?: boolean } = {}): void {
229
231
  if (mode === "image" && streaming) {
230
232
  recording = !recording;
231
233
  }
232
- if (mode === "image") {
233
- take_picture();
234
- } else {
235
- take_recording();
234
+
235
+ if (!destroy) {
236
+ if (mode === "image") {
237
+ take_picture();
238
+ } else {
239
+ take_recording();
240
+ }
236
241
  }
242
+
237
243
  if (!recording && stream) {
238
244
  dispatch("close_stream");
239
245
  stream.getTracks().forEach((track) => track.stop());
@@ -273,6 +279,12 @@
273
279
  event.stopPropagation();
274
280
  options_open = false;
275
281
  }
282
+
283
+ onDestroy(() => {
284
+ if (typeof window === "undefined") return;
285
+ record_video_or_photo({ destroy: true });
286
+ stream?.getTracks().forEach((track) => track.stop());
287
+ });
276
288
  </script>
277
289
 
278
290
  <div class="wrap">
@@ -300,7 +312,7 @@
300
312
  {:else}
301
313
  <div class="button-wrap">
302
314
  <button
303
- on:click={record_video_or_photo}
315
+ on:click={() => record_video_or_photo()}
304
316
  aria-label={mode === "image" ? "capture photo" : "start recording"}
305
317
  >
306
318
  {#if mode === "video" || streaming}