HongzeFu commited on
Commit
9e3dbca
·
1 Parent(s): a7b9f8e

fix video display v1

Browse files
gradio-web/config.py CHANGED
@@ -40,7 +40,7 @@ DEMO_VIDEO_ENV_IDS = [
40
 
41
  UI_TEXT = {
42
  "log": {
43
- "action_selection_prompt": "please select the action in the right 👈,\nsome actions also need to select keypoint",
44
  "demo_video_prompt": 'press "Watch Video Input🎬" to watch a video\nNote: you can only watch the video once',
45
  "session_error": "Session Error",
46
  "reference_action_error": "Ground Truth Action Error: {error}",
 
40
 
41
  UI_TEXT = {
42
  "log": {
43
+ "action_selection_prompt": "please select the action in the left 👈,\nsome actions also need to select keypoint",
44
  "demo_video_prompt": 'press "Watch Video Input🎬" to watch a video\nNote: you can only watch the video once',
45
  "session_error": "Session Error",
46
  "reference_action_error": "Ground Truth Action Error: {error}",
gradio-web/test/test_ui_phase_machine_runtime_e2e.py CHANGED
@@ -100,6 +100,29 @@ def _read_coords_box_value(page) -> str | None:
100
  )
101
 
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  def _read_live_obs_geometry(page) -> dict[str, dict[str, float] | None]:
104
  return page.evaluate(
105
  """() => {
@@ -1051,6 +1074,172 @@ def test_header_task_env_normalization_and_fallback(monkeypatch, task_info_text,
1051
  demo.close()
1052
 
1053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1054
  def test_phase_machine_runtime_local_video_path_end_transition():
1055
  import gradio_callbacks as cb
1056
 
 
100
  )
101
 
102
 
103
+ def _read_phase_visibility(page) -> dict[str, bool | str | None]:
104
+ return page.evaluate(
105
+ """() => {
106
+ const visible = (id) => {
107
+ const el = document.getElementById(id);
108
+ if (!el) return false;
109
+ const st = getComputedStyle(el);
110
+ return st.display !== 'none' && st.visibility !== 'hidden' && el.getClientRects().length > 0;
111
+ };
112
+ const videoEl = document.querySelector('#demo_video video');
113
+ return {
114
+ videoPhase: visible('video_phase_group'),
115
+ video: visible('demo_video'),
116
+ actionPhase: visible('action_phase_group'),
117
+ action: visible('live_obs'),
118
+ controlPhase: visible('control_panel_group'),
119
+ control: visible('action_radio'),
120
+ currentSrc: videoEl ? videoEl.currentSrc : null,
121
+ };
122
+ }"""
123
+ )
124
+
125
+
126
  def _read_live_obs_geometry(page) -> dict[str, dict[str, float] | None]:
127
  return page.evaluate(
128
  """() => {
 
1074
  demo.close()
1075
 
1076
 
1077
+ def test_header_task_switch_to_video_task_shows_demo_phase(monkeypatch):
1078
+ ui_layout = importlib.reload(importlib.import_module("ui_layout"))
1079
+
1080
+ fake_obs = np.zeros((24, 24, 3), dtype=np.uint8)
1081
+ fake_obs_img = Image.fromarray(fake_obs)
1082
+ demo_video_path = gr.get_video("world.mp4")
1083
+ switch_calls = []
1084
+
1085
+ def fake_init_app(request=None):
1086
+ _ = request
1087
+ return (
1088
+ "uid-header-video",
1089
+ gr.update(visible=True), # main_interface
1090
+ gr.update(value=fake_obs_img, interactive=False), # img_display
1091
+ "ready", # log_output
1092
+ gr.update(choices=[("pick", 0)], value=None), # options_radio
1093
+ "goal", # goal_box
1094
+ "No need for coordinates", # coords_box
1095
+ gr.update(value=None, visible=False), # video_display
1096
+ "PickXtimes (Episode 1)", # task_info_box
1097
+ "Completed: 0", # progress_info_box
1098
+ gr.update(interactive=True), # restart_episode_btn
1099
+ gr.update(interactive=True), # next_task_btn
1100
+ gr.update(interactive=True), # exec_btn
1101
+ gr.update(visible=False), # video_phase_group
1102
+ gr.update(visible=True), # action_phase_group
1103
+ gr.update(visible=True), # control_panel_group
1104
+ gr.update(value="hint"), # task_hint_display
1105
+ gr.update(visible=False), # loading_overlay
1106
+ gr.update(interactive=True), # reference_action_btn
1107
+ )
1108
+
1109
+ def fake_switch_env_wrapper(uid, selected_env):
1110
+ switch_calls.append((uid, selected_env))
1111
+ return (
1112
+ uid,
1113
+ gr.update(visible=True), # main_interface
1114
+ gr.update(value=fake_obs_img, interactive=False), # img_display
1115
+ "demo prompt", # log_output
1116
+ gr.update(choices=[("pick", 0)], value=None), # options_radio
1117
+ "video goal", # goal_box
1118
+ "No need for coordinates", # coords_box
1119
+ gr.update(value=demo_video_path, visible=True), # video_display
1120
+ "VideoPlaceButton (Episode 1)", # task_info_box
1121
+ "Completed: 0", # progress_info_box
1122
+ gr.update(interactive=True), # restart_episode_btn
1123
+ gr.update(interactive=True), # next_task_btn
1124
+ gr.update(interactive=True), # exec_btn
1125
+ gr.update(visible=True), # video_phase_group
1126
+ gr.update(visible=False), # action_phase_group
1127
+ gr.update(visible=False), # control_panel_group
1128
+ gr.update(value="video hint"), # task_hint_display
1129
+ gr.update(visible=False), # loading_overlay
1130
+ gr.update(interactive=True), # reference_action_btn
1131
+ )
1132
+
1133
+ monkeypatch.setattr(ui_layout, "init_app", fake_init_app)
1134
+ monkeypatch.setattr(ui_layout, "switch_env_wrapper", fake_switch_env_wrapper)
1135
+ monkeypatch.setattr(ui_layout.user_manager, "env_choices", ["PickXtimes", "VideoPlaceButton"])
1136
+
1137
+ demo = ui_layout.create_ui_blocks()
1138
+
1139
+ port = _free_port()
1140
+ host = "127.0.0.1"
1141
+ root_url = f"http://{host}:{port}/"
1142
+
1143
+ app = FastAPI(title="header-task-switch-video-phase-test")
1144
+ app = gr.mount_gradio_app(app, demo, path="/")
1145
+
1146
+ config = uvicorn.Config(app, host=host, port=port, log_level="error")
1147
+ server = uvicorn.Server(config)
1148
+ thread = threading.Thread(target=server.run, daemon=True)
1149
+ thread.start()
1150
+ _wait_http_ready(root_url)
1151
+
1152
+ try:
1153
+ with sync_playwright() as p:
1154
+ browser = p.chromium.launch(headless=True)
1155
+ page = browser.new_page(viewport={"width": 1280, "height": 900})
1156
+ page.goto(root_url, wait_until="domcontentloaded")
1157
+ page.wait_for_selector("#main_interface_root", state="visible", timeout=15000)
1158
+ page.wait_for_function(
1159
+ """() => {
1160
+ const root = document.getElementById('header_task');
1161
+ const input = root ? root.querySelector('input') : null;
1162
+ return !!input && input.value.trim() === 'PickXtimes';
1163
+ }""",
1164
+ timeout=5000,
1165
+ )
1166
+
1167
+ page.click("#header_task input")
1168
+ page.get_by_role("option", name="VideoPlaceButton").click()
1169
+
1170
+ page.wait_for_function(
1171
+ """() => {
1172
+ const visible = (id) => {
1173
+ const el = document.getElementById(id);
1174
+ if (!el) return false;
1175
+ const st = getComputedStyle(el);
1176
+ return st.display !== 'none' && st.visibility !== 'hidden' && el.getClientRects().length > 0;
1177
+ };
1178
+ const videoEl = document.querySelector('#demo_video video');
1179
+ return (
1180
+ visible('video_phase_group') &&
1181
+ visible('demo_video') &&
1182
+ !visible('action_phase_group') &&
1183
+ !visible('control_panel_group') &&
1184
+ !!(videoEl && videoEl.currentSrc)
1185
+ );
1186
+ }""",
1187
+ timeout=10000,
1188
+ )
1189
+
1190
+ phase_after_switch = _read_phase_visibility(page)
1191
+ assert phase_after_switch["videoPhase"] is True
1192
+ assert phase_after_switch["video"] is True
1193
+ assert phase_after_switch["actionPhase"] is False
1194
+ assert phase_after_switch["controlPhase"] is False
1195
+ assert phase_after_switch["currentSrc"]
1196
+ assert switch_calls == [("uid-header-video", "VideoPlaceButton")]
1197
+
1198
+ did_dispatch_end = page.evaluate(
1199
+ """() => {
1200
+ const videoEl = document.querySelector('#demo_video video');
1201
+ if (!videoEl) return false;
1202
+ videoEl.dispatchEvent(new Event('ended', { bubbles: true }));
1203
+ return true;
1204
+ }"""
1205
+ )
1206
+ assert did_dispatch_end
1207
+
1208
+ page.wait_for_function(
1209
+ """() => {
1210
+ const visible = (id) => {
1211
+ const el = document.getElementById(id);
1212
+ if (!el) return false;
1213
+ const st = getComputedStyle(el);
1214
+ return st.display !== 'none' && st.visibility !== 'hidden' && el.getClientRects().length > 0;
1215
+ };
1216
+ return (
1217
+ !visible('video_phase_group') &&
1218
+ !visible('demo_video') &&
1219
+ visible('action_phase_group') &&
1220
+ visible('control_panel_group') &&
1221
+ visible('live_obs') &&
1222
+ visible('action_radio')
1223
+ );
1224
+ }""",
1225
+ timeout=5000,
1226
+ )
1227
+
1228
+ phase_after_end = _read_phase_visibility(page)
1229
+ assert phase_after_end["videoPhase"] is False
1230
+ assert phase_after_end["video"] is False
1231
+ assert phase_after_end["actionPhase"] is True
1232
+ assert phase_after_end["action"] is True
1233
+ assert phase_after_end["controlPhase"] is True
1234
+ assert phase_after_end["control"] is True
1235
+
1236
+ browser.close()
1237
+ finally:
1238
+ server.should_exit = True
1239
+ thread.join(timeout=10)
1240
+ demo.close()
1241
+
1242
+
1243
  def test_phase_machine_runtime_local_video_path_end_transition():
1244
  import gradio_callbacks as cb
1245
 
gradio-web/ui_layout.py CHANGED
@@ -290,6 +290,30 @@ def _with_phase_from_load(load_result):
290
  return (*load_result, phase)
291
 
292
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  def create_ui_blocks():
294
  """构建 Gradio Blocks,并完成页面阶段状态(phase)的联动绑定。"""
295
 
@@ -337,6 +361,8 @@ def create_ui_blocks():
337
 
338
  uid_state = gr.State(value=None)
339
  ui_phase_state = gr.State(value=PHASE_INIT)
 
 
340
  live_obs_timer = gr.Timer(value=1.0 / LIVE_OBS_REFRESH_HZ, active=True)
341
 
342
  task_info_box = gr.Textbox(visible=False, elem_id="task_info_box")
@@ -450,6 +476,34 @@ def create_ui_blocks():
450
  elem_id="task_hint_display",
451
  )
452
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  def _normalize_env_choice(env_value, choices):
454
  if env_value is None:
455
  return None
@@ -463,7 +517,7 @@ def create_ui_blocks():
463
  lower_map.setdefault(choice_text.lower(), choice_text)
464
  return lower_map.get(env_text.lower(), env_text)
465
 
466
- def _build_header_task_update(task_text, fallback_env=None):
467
  base_choices = list(user_manager.env_choices)
468
  parsed_env = render_header_task(task_text)
469
  selected_env = _normalize_env_choice(parsed_env, base_choices)
@@ -473,13 +527,23 @@ def create_ui_blocks():
473
  choices = list(base_choices)
474
  if selected_env and selected_env not in choices:
475
  choices.append(selected_env)
 
 
 
 
476
  return gr.update(choices=choices, value=selected_env)
477
 
478
  def sync_header_from_task(task_text, goal_text):
479
- return _build_header_task_update(task_text), render_header_goal(goal_text)
 
480
 
481
  def sync_header_from_goal(goal_text, task_text, current_header_task):
482
- return _build_header_task_update(task_text, fallback_env=current_header_task), render_header_goal(goal_text)
 
 
 
 
 
483
 
484
  def init_app_with_phase(request: gr.Request):
485
  return _with_phase_from_load(init_app(request))
@@ -493,108 +557,87 @@ def create_ui_blocks():
493
  def switch_env_with_phase(uid, selected_env):
494
  return _with_phase_from_load(switch_env_wrapper(uid, selected_env))
495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  task_info_box.change(
497
  fn=sync_header_from_task,
498
  inputs=[task_info_box, goal_box],
499
- outputs=[header_task_box, header_goal_box],
500
  )
501
  goal_box.change(
502
  fn=sync_header_from_goal,
503
  inputs=[goal_box, task_info_box, header_task_box],
504
- outputs=[header_task_box, header_goal_box],
505
  )
506
 
507
- header_task_box.input(fn=show_loading_info, outputs=[loading_overlay]).then(
508
- fn=switch_env_with_phase,
509
- inputs=[uid_state, header_task_box],
510
- outputs=[
511
- uid_state,
512
- main_interface,
513
- img_display,
514
- log_output,
515
- options_radio,
516
- goal_box,
517
- coords_box,
518
- video_display,
519
- task_info_box,
520
- progress_info_box,
521
- restart_episode_btn,
522
- next_task_btn,
523
- exec_btn,
524
- video_phase_group,
525
- action_phase_group,
526
- control_panel_group,
527
- task_hint_display,
528
- loading_overlay,
529
- reference_action_btn,
530
- ui_phase_state,
531
- ],
532
  ).then(
533
- fn=sync_header_from_task,
534
- inputs=[task_info_box, goal_box],
535
- outputs=[header_task_box, header_goal_box],
 
 
 
 
 
 
 
 
 
 
 
 
536
  )
537
 
538
  next_task_btn.click(fn=show_loading_info, outputs=[loading_overlay]).then(
539
  fn=load_next_task_with_phase,
540
  inputs=[uid_state],
541
- outputs=[
542
- uid_state,
543
- main_interface,
544
- img_display,
545
- log_output,
546
- options_radio,
547
- goal_box,
548
- coords_box,
549
- video_display,
550
- task_info_box,
551
- progress_info_box,
552
- restart_episode_btn,
553
- next_task_btn,
554
- exec_btn,
555
- video_phase_group,
556
- action_phase_group,
557
- control_panel_group,
558
- task_hint_display,
559
- loading_overlay,
560
- reference_action_btn,
561
- ui_phase_state,
562
- ],
563
  ).then(
564
  fn=sync_header_from_task,
565
  inputs=[task_info_box, goal_box],
566
- outputs=[header_task_box, header_goal_box],
567
  )
568
 
569
  restart_episode_btn.click(fn=show_loading_info, outputs=[loading_overlay]).then(
570
  fn=restart_episode_with_phase,
571
  inputs=[uid_state],
572
- outputs=[
573
- uid_state,
574
- main_interface,
575
- img_display,
576
- log_output,
577
- options_radio,
578
- goal_box,
579
- coords_box,
580
- video_display,
581
- task_info_box,
582
- progress_info_box,
583
- restart_episode_btn,
584
- next_task_btn,
585
- exec_btn,
586
- video_phase_group,
587
- action_phase_group,
588
- control_panel_group,
589
- task_hint_display,
590
- loading_overlay,
591
- reference_action_btn,
592
- ui_phase_state,
593
- ],
594
  ).then(
595
  fn=sync_header_from_task,
596
  inputs=[task_info_box, goal_box],
597
- outputs=[header_task_box, header_goal_box],
598
  )
599
 
600
  video_display.end(
@@ -701,32 +744,17 @@ def create_ui_blocks():
701
  demo.load(
702
  fn=init_app_with_phase,
703
  inputs=[],
704
- outputs=[
705
- uid_state,
706
- main_interface,
707
- img_display,
708
- log_output,
709
- options_radio,
710
- goal_box,
711
- coords_box,
712
- video_display,
713
- task_info_box,
714
- progress_info_box,
715
- restart_episode_btn,
716
- next_task_btn,
717
- exec_btn,
718
- video_phase_group,
719
- action_phase_group,
720
- control_panel_group,
721
- task_hint_display,
722
- loading_overlay,
723
- reference_action_btn,
724
- ui_phase_state,
725
- ],
726
  ).then(
727
  fn=sync_header_from_task,
728
  inputs=[task_info_box, goal_box],
729
- outputs=[header_task_box, header_goal_box],
730
  )
731
 
732
  return demo
 
290
  return (*load_result, phase)
291
 
292
 
293
+ def _skip_load_flow():
294
+ return tuple(gr.skip() for _ in range(20))
295
+
296
+
297
+ def _phase_visibility_updates(phase):
298
+ if phase == PHASE_DEMO_VIDEO:
299
+ return (
300
+ gr.update(visible=True),
301
+ gr.update(visible=False),
302
+ gr.update(visible=False),
303
+ )
304
+ if phase in {PHASE_ACTION_KEYPOINT, PHASE_EXECUTION_PLAYBACK}:
305
+ return (
306
+ gr.update(visible=False),
307
+ gr.update(visible=True),
308
+ gr.update(visible=True),
309
+ )
310
+ return (
311
+ gr.update(visible=False),
312
+ gr.update(visible=False),
313
+ gr.update(visible=False),
314
+ )
315
+
316
+
317
  def create_ui_blocks():
318
  """构建 Gradio Blocks,并完成页面阶段状态(phase)的联动绑定。"""
319
 
 
361
 
362
  uid_state = gr.State(value=None)
363
  ui_phase_state = gr.State(value=PHASE_INIT)
364
+ pending_header_task_state = gr.State(value=None)
365
+ programmatic_header_task_state = gr.State(value=None)
366
  live_obs_timer = gr.Timer(value=1.0 / LIVE_OBS_REFRESH_HZ, active=True)
367
 
368
  task_info_box = gr.Textbox(visible=False, elem_id="task_info_box")
 
476
  elem_id="task_hint_display",
477
  )
478
 
479
+ load_flow_outputs = [
480
+ uid_state,
481
+ main_interface,
482
+ img_display,
483
+ log_output,
484
+ options_radio,
485
+ goal_box,
486
+ coords_box,
487
+ video_display,
488
+ task_info_box,
489
+ progress_info_box,
490
+ restart_episode_btn,
491
+ next_task_btn,
492
+ exec_btn,
493
+ video_phase_group,
494
+ action_phase_group,
495
+ control_panel_group,
496
+ task_hint_display,
497
+ loading_overlay,
498
+ reference_action_btn,
499
+ ui_phase_state,
500
+ ]
501
+ phase_visibility_outputs = [
502
+ video_phase_group,
503
+ action_phase_group,
504
+ control_panel_group,
505
+ ]
506
+
507
  def _normalize_env_choice(env_value, choices):
508
  if env_value is None:
509
  return None
 
517
  lower_map.setdefault(choice_text.lower(), choice_text)
518
  return lower_map.get(env_text.lower(), env_text)
519
 
520
+ def _resolve_header_task_state(task_text, fallback_env=None):
521
  base_choices = list(user_manager.env_choices)
522
  parsed_env = render_header_task(task_text)
523
  selected_env = _normalize_env_choice(parsed_env, base_choices)
 
527
  choices = list(base_choices)
528
  if selected_env and selected_env not in choices:
529
  choices.append(selected_env)
530
+ return choices, selected_env
531
+
532
+ def _build_header_task_update(task_text, fallback_env=None):
533
+ choices, selected_env = _resolve_header_task_state(task_text, fallback_env=fallback_env)
534
  return gr.update(choices=choices, value=selected_env)
535
 
536
  def sync_header_from_task(task_text, goal_text):
537
+ _, selected_env = _resolve_header_task_state(task_text)
538
+ return _build_header_task_update(task_text), render_header_goal(goal_text), selected_env
539
 
540
  def sync_header_from_goal(goal_text, task_text, current_header_task):
541
+ _, selected_env = _resolve_header_task_state(task_text, fallback_env=current_header_task)
542
+ return (
543
+ _build_header_task_update(task_text, fallback_env=current_header_task),
544
+ render_header_goal(goal_text),
545
+ selected_env,
546
+ )
547
 
548
  def init_app_with_phase(request: gr.Request):
549
  return _with_phase_from_load(init_app(request))
 
557
  def switch_env_with_phase(uid, selected_env):
558
  return _with_phase_from_load(switch_env_wrapper(uid, selected_env))
559
 
560
+ def maybe_switch_env_with_phase(uid, selected_env):
561
+ if not selected_env:
562
+ return _skip_load_flow()
563
+ return switch_env_with_phase(uid, selected_env)
564
+
565
+ def prepare_header_task_switch(selected_env, programmatic_selected_env):
566
+ base_choices = list(user_manager.env_choices)
567
+ normalized_selected_env = _normalize_env_choice(selected_env, base_choices)
568
+ normalized_programmatic_env = _normalize_env_choice(programmatic_selected_env, base_choices)
569
+
570
+ if not normalized_selected_env:
571
+ return None, None, gr.update(visible=False)
572
+ if normalized_selected_env == normalized_programmatic_env:
573
+ return None, None, gr.update(visible=False)
574
+ return normalized_selected_env, None, show_loading_info()
575
+
576
  task_info_box.change(
577
  fn=sync_header_from_task,
578
  inputs=[task_info_box, goal_box],
579
+ outputs=[header_task_box, header_goal_box, programmatic_header_task_state],
580
  )
581
  goal_box.change(
582
  fn=sync_header_from_goal,
583
  inputs=[goal_box, task_info_box, header_task_box],
584
+ outputs=[header_task_box, header_goal_box, programmatic_header_task_state],
585
  )
586
 
587
+ header_task_box.change(
588
+ fn=prepare_header_task_switch,
589
+ inputs=[header_task_box, programmatic_header_task_state],
590
+ outputs=[pending_header_task_state, programmatic_header_task_state, loading_overlay],
591
+ queue=False,
592
+ show_progress="hidden",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  ).then(
594
+ fn=maybe_switch_env_with_phase,
595
+ inputs=[uid_state, pending_header_task_state],
596
+ outputs=load_flow_outputs,
597
+ ).then(
598
+ fn=_phase_visibility_updates,
599
+ inputs=[ui_phase_state],
600
+ outputs=phase_visibility_outputs,
601
+ queue=False,
602
+ show_progress="hidden",
603
+ ).then(
604
+ fn=lambda _selected_env: None,
605
+ inputs=[pending_header_task_state],
606
+ outputs=[pending_header_task_state],
607
+ queue=False,
608
+ show_progress="hidden",
609
  )
610
 
611
  next_task_btn.click(fn=show_loading_info, outputs=[loading_overlay]).then(
612
  fn=load_next_task_with_phase,
613
  inputs=[uid_state],
614
+ outputs=load_flow_outputs,
615
+ ).then(
616
+ fn=_phase_visibility_updates,
617
+ inputs=[ui_phase_state],
618
+ outputs=phase_visibility_outputs,
619
+ queue=False,
620
+ show_progress="hidden",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  ).then(
622
  fn=sync_header_from_task,
623
  inputs=[task_info_box, goal_box],
624
+ outputs=[header_task_box, header_goal_box, programmatic_header_task_state],
625
  )
626
 
627
  restart_episode_btn.click(fn=show_loading_info, outputs=[loading_overlay]).then(
628
  fn=restart_episode_with_phase,
629
  inputs=[uid_state],
630
+ outputs=load_flow_outputs,
631
+ ).then(
632
+ fn=_phase_visibility_updates,
633
+ inputs=[ui_phase_state],
634
+ outputs=phase_visibility_outputs,
635
+ queue=False,
636
+ show_progress="hidden",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  ).then(
638
  fn=sync_header_from_task,
639
  inputs=[task_info_box, goal_box],
640
+ outputs=[header_task_box, header_goal_box, programmatic_header_task_state],
641
  )
642
 
643
  video_display.end(
 
744
  demo.load(
745
  fn=init_app_with_phase,
746
  inputs=[],
747
+ outputs=load_flow_outputs,
748
+ ).then(
749
+ fn=_phase_visibility_updates,
750
+ inputs=[ui_phase_state],
751
+ outputs=phase_visibility_outputs,
752
+ queue=False,
753
+ show_progress="hidden",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
754
  ).then(
755
  fn=sync_header_from_task,
756
  inputs=[task_info_box, goal_box],
757
+ outputs=[header_task_box, header_goal_box, programmatic_header_task_state],
758
  )
759
 
760
  return demo