Skip to content

Commit 4552df4

Browse files
Fix status tracker iterative image (#12358)
* Fix dropdown filtering * Fix * add changeset * Fix issue finally for real * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
1 parent 761d14b commit 4552df4

File tree

3 files changed

+133
-87
lines changed

3 files changed

+133
-87
lines changed

.changeset/shiny-paws-tease.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@gradio/core": minor
3+
"@gradio/statustracker": minor
4+
"gradio": minor
5+
---
6+
7+
feat:Fix status tracker iterative image

js/core/src/init.svelte.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
get_inputs_outputs
55
} from "./init_utils";
66
import { translate_if_needed } from "./i18n";
7+
import { tick } from "svelte";
78

89
import type {
910
ComponentMeta,
@@ -329,6 +330,7 @@ export class AppTree {
329330
const node = find_node_by_id(this.root!, id);
330331
let already_updated_visibility = false;
331332
if (check_visibility && !node?.component) {
333+
await tick();
332334
this.root = this.traverse(this.root!, [
333335
//@ts-ignore
334336
(n) => set_visibility_for_updated_node(n, id, new_state.visible),
@@ -340,6 +342,9 @@ export class AppTree {
340342
if (!_set_data) return;
341343
_set_data(new_state);
342344
if (!check_visibility || already_updated_visibility) return;
345+
// need to let the UI settle before traversing again
346+
// otherwise there could be
347+
await tick();
343348
this.root = this.traverse(this.root!, (n) =>
344349
handle_visibility(n, this.#config.root)
345350
);

js/statustracker/static/index.svelte

Lines changed: 121 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -50,75 +50,106 @@
5050
</script>
5151

5252
<script lang="ts">
53-
import { onDestroy } from "svelte";
54-
5553
import Loader from "./Loader.svelte";
5654
import type { LoadingStatus } from "./types";
5755
import type { I18nFormatter } from "@gradio/utils";
58-
import { createEventDispatcher } from "svelte";
5956
6057
import { IconButton } from "@gradio/atoms";
6158
import { Clear } from "@gradio/icons";
6259
63-
const dispatch = createEventDispatcher();
64-
65-
export let i18n: I18nFormatter;
66-
export let eta: number | null = null;
67-
export let queue_position: number | null;
68-
export let queue_size: number | null;
69-
export let status:
70-
| "complete"
71-
| "pending"
72-
| "error"
73-
| "generating"
74-
| "streaming"
75-
| null;
76-
export let scroll_to_output = false;
77-
export let timer = true;
78-
export let show_progress: "full" | "minimal" | "hidden" = "full";
79-
export let message: string | null = null;
80-
export let progress: LoadingStatus["progress"] | null | undefined = null;
81-
export let variant: "default" | "center" = "default";
82-
export let loading_text = "Loading...";
83-
export let absolute = true;
84-
export let translucent = false;
85-
export let border = false;
86-
export let autoscroll: boolean;
87-
export let validation_error: string | null = null;
88-
export let show_validation_error = true;
89-
export let type: "input" | "outputs" | null = null;
90-
91-
$: should_hide =
92-
type === "input" ||
93-
!status ||
94-
status === "complete" ||
95-
show_progress === "hidden" ||
96-
status == "streaming" ||
97-
(show_validation_error && validation_error);
60+
interface Props {
61+
i18n: I18nFormatter;
62+
eta?: number | null;
63+
queue_position: number | null;
64+
queue_size: number | null;
65+
status:
66+
| "complete"
67+
| "pending"
68+
| "error"
69+
| "generating"
70+
| "streaming"
71+
| null;
72+
scroll_to_output?: boolean;
73+
timer?: boolean;
74+
show_progress?: "full" | "minimal" | "hidden";
75+
message?: string | null;
76+
progress?: LoadingStatus["progress"] | null | undefined;
77+
variant?: "default" | "center";
78+
loading_text?: string;
79+
absolute?: boolean;
80+
translucent?: boolean;
81+
border?: boolean;
82+
autoscroll: boolean;
83+
validation_error?: string | null;
84+
show_validation_error?: boolean;
85+
type?: "input" | "output" | null;
86+
on_clear_status?: () => void;
87+
}
88+
89+
let {
90+
i18n,
91+
eta = null,
92+
queue_position,
93+
queue_size,
94+
status,
95+
scroll_to_output = false,
96+
timer = true,
97+
show_progress = "full",
98+
message = null,
99+
progress = null,
100+
variant = "default",
101+
loading_text = "Loading...",
102+
absolute = true,
103+
translucent = false,
104+
border = false,
105+
autoscroll,
106+
validation_error = null,
107+
show_validation_error = true,
108+
type = null,
109+
on_clear_status
110+
}: Props = $props();
98111
99112
let el: HTMLDivElement;
100113
101-
let _timer = false;
102-
let timer_start = 0;
103-
let timer_diff = 0;
104-
let old_eta: number | null = null;
105-
let eta_from_start: number | null = null;
106-
let message_visible = false;
107-
let eta_level: number | null = 0;
108-
let progress_level: (number | undefined)[] | null = null;
109-
let last_progress_level: number | undefined = undefined;
110-
let progress_bar: HTMLElement | null = null;
111-
let show_eta_bar = true;
112-
113-
$: eta_level =
114+
let _timer = $state(false);
115+
let timer_start = $state(0);
116+
let timer_diff = $state(0);
117+
let old_eta = $state<number | null>(null);
118+
let eta_from_start = $state<number | null>(null);
119+
let message_visible = $state(false);
120+
let progress_level = $state<(number | undefined)[] | null>(null);
121+
let last_progress_level = $state<number | undefined>(undefined);
122+
let progress_bar = $state<HTMLElement | null>(null);
123+
let show_eta_bar = $state(true);
124+
let formatted_eta = $state<string | null>(null);
125+
let show_message_timeout = $state<NodeJS.Timeout | null>(null);
126+
127+
const should_hide = $derived(
128+
type === "input" ||
129+
!status ||
130+
status === "complete" ||
131+
show_progress === "hidden" ||
132+
status == "streaming" ||
133+
!!(show_validation_error && validation_error)
134+
);
135+
136+
const eta_level = $derived(
114137
eta_from_start === null || eta_from_start <= 0 || !timer_diff
115138
? null
116-
: Math.min(timer_diff / eta_from_start, 1);
117-
$: if (progress != null) {
118-
show_eta_bar = false;
119-
}
139+
: Math.min(timer_diff / eta_from_start, 1)
140+
);
141+
142+
const formatted_timer = $derived(timer_diff.toFixed(1));
143+
144+
$effect(() => {
145+
if (progress != null) {
146+
show_eta_bar = false;
147+
} else {
148+
show_eta_bar = true;
149+
}
150+
});
120151
121-
$: {
152+
$effect(() => {
122153
if (progress != null) {
123154
progress_level = progress.map((p) => {
124155
if (p.index != null && p.length != null) {
@@ -144,15 +175,7 @@
144175
} else {
145176
last_progress_level = undefined;
146177
}
147-
}
148-
149-
const start_timer = (): void => {
150-
eta = old_eta = formatted_eta = null;
151-
timer_start = performance.now();
152-
timer_diff = 0;
153-
_timer = true;
154-
run();
155-
};
178+
});
156179
157180
function run(): void {
158181
raf(() => {
@@ -161,33 +184,44 @@
161184
});
162185
}
163186
164-
function stop_timer(): void {
187+
function start_timer(): void {
188+
old_eta = formatted_eta = null;
189+
timer_start = performance.now();
165190
timer_diff = 0;
166-
eta = old_eta = formatted_eta = null;
191+
_timer = true;
192+
run();
193+
}
167194
195+
function stop_timer(): void {
196+
timer_diff = 0;
197+
old_eta = formatted_eta = null;
168198
if (!_timer) return;
169199
_timer = false;
170200
}
171201
172-
onDestroy(() => {
173-
if (_timer) stop_timer();
174-
});
175-
176-
$: {
202+
$effect(() => {
177203
if (status === "pending") {
178204
start_timer();
179205
} else {
180206
stop_timer();
181207
}
182-
}
183208
184-
$: el &&
185-
scroll_to_output &&
186-
(status === "pending" || status === "complete") &&
187-
scroll_into_view(el, autoscroll);
209+
return () => {
210+
if (_timer) stop_timer();
211+
};
212+
});
188213
189-
let formatted_eta: string | null = null;
190-
$: {
214+
$effect(() => {
215+
if (
216+
el &&
217+
scroll_to_output &&
218+
(status === "pending" || status === "complete")
219+
) {
220+
scroll_into_view(el, autoscroll);
221+
}
222+
});
223+
224+
$effect(() => {
191225
if (eta === null) {
192226
eta = old_eta;
193227
}
@@ -196,21 +230,21 @@
196230
formatted_eta = eta_from_start.toFixed(1);
197231
old_eta = eta;
198232
}
199-
}
200-
let show_message_timeout: NodeJS.Timeout | null = null;
233+
});
234+
201235
function close_message(): void {
202236
message_visible = false;
203237
if (show_message_timeout !== null) {
204238
clearTimeout(show_message_timeout);
205239
}
206240
}
207-
$: {
241+
242+
$effect(() => {
208243
close_message();
209244
if (status === "error" && message) {
210245
message_visible = true;
211246
}
212-
}
213-
$: formatted_timer = timer_diff.toFixed(1);
247+
});
214248
</script>
215249

216250
<div
@@ -240,7 +274,7 @@
240274
background="var(--background-fill-primary)"
241275
color="var(--error-background-text)"
242276
border="var(--border-color-primary)"
243-
on:click={() => (validation_error = null)}
277+
onclick={() => (validation_error = null)}
244278
/></button
245279
>
246280
</div>
@@ -324,8 +358,8 @@
324358
Icon={Clear}
325359
label={i18n("common.clear")}
326360
disabled={false}
327-
on:click={() => {
328-
dispatch("clear_status");
361+
onclick={() => {
362+
on_clear_status?.();
329363
}}
330364
/>
331365
</div>

0 commit comments

Comments
 (0)