@@ -39,6 +39,7 @@ def __init__(
3939 self ._scrollwidget : bui .Widget | None = None
4040 self ._columnwidget : bui .Widget | None = None
4141 self ._my_replay_selected : str | None = None
42+ self ._replay_play_in_flight = False
4243 self ._my_replays_rename_window : bui .Widget | None = None
4344 self ._my_replay_rename_text : bui .Widget | None = None
4445 self ._r = 'watchWindow'
@@ -394,6 +395,13 @@ def _on_my_replay_play_press(self) -> None:
394395 self ._start_replay_playback ()
395396
396397 def _start_replay_playback (self ) -> None :
398+ # A double press (or a second confirm) would otherwise spawn two
399+ # concurrent launch tasks: two launch_replay calls and a second
400+ # transition-out on our root widget (seen in the field as
401+ # 'ContainerWidget was set to transition out twice' reports).
402+ if self ._replay_play_in_flight :
403+ return
404+ self ._replay_play_in_flight = True
397405 bui .app .create_async_task (self ._prepare_and_play_replay ())
398406
399407 async def _prepare_and_play_replay (self ) -> None :
@@ -406,6 +414,9 @@ async def _prepare_and_play_replay(self) -> None:
406414 # stranding them on a torn-down UI (mirrors how connect_to_party
407415 # preps with the gather UI still present).
408416 if not await bs .prepare_replay (path ):
417+ # Prep failed/cancelled; we're staying here, so allow
418+ # another play attempt.
419+ self ._replay_play_in_flight = False
409420 return
410421
411422 # Content is ready; now do the fade-out -> launch -> fade-in and
@@ -431,7 +442,11 @@ def do_it() -> None:
431442 bs .new_host_session (mainmenu .MainMenuSession )
432443
433444 bui .fade_screen (False , endcall = bui .CallStrict (bui .pushcall , do_it ))
434- bui .containerwidget (edit = self ._root_widget , transition = 'out_left' )
445+ # The user may have navigated away during the async prep above,
446+ # in which case our window is already gone or on its way out;
447+ # transitioning it out again logs a warning.
448+ if self ._root_widget and not self ._root_widget .transitioning_out :
449+ bui .containerwidget (edit = self ._root_widget , transition = 'out_left' )
435450
436451 def _on_my_replay_rename_press (self ) -> None :
437452 if self ._my_replay_selected is None :
0 commit comments