Skip to content

Commit 8388449

Browse files
authored
fix: auto refresh recents page (#1212)
# Motivation <!-- Why is this change necessary? --> # Content <!-- Please include a summary of the change --> # Testing <!-- How was the change tested? --> # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed
1 parent 014b60b commit 8388449

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/codegen/cli/tui/app.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import tty
77
from datetime import datetime
88
from typing import Any
9+
import threading
10+
import time
911

1012
import requests
1113
import typer
@@ -35,14 +37,66 @@ def __init__(self):
3537
self.tabs = ["recents", "new", "web"]
3638
self.current_tab = 0
3739

40+
# Refresh state
41+
self.is_refreshing = False
42+
self._auto_refresh_interval_seconds = 10
43+
self._refresh_lock = threading.Lock()
44+
3845
# New tab state
3946
self.prompt_input = ""
47+
4048
self.cursor_position = 0
4149
self.input_mode = False # When true, we're typing in the input box
4250

4351
# Set up signal handler for Ctrl+C
4452
signal.signal(signal.SIGINT, self._signal_handler)
4553

54+
# Start background auto-refresh thread (daemon)
55+
self._auto_refresh_thread = threading.Thread(target=self._auto_refresh_loop, daemon=True)
56+
self._auto_refresh_thread.start()
57+
58+
def _auto_refresh_loop(self):
59+
"""Background loop to auto-refresh recents tab every interval."""
60+
while True:
61+
# Sleep first so we don't immediately spam a refresh on start
62+
time.sleep(self._auto_refresh_interval_seconds)
63+
64+
if not self.running:
65+
break
66+
67+
# Only refresh when on recents tab and not currently refreshing
68+
if self.current_tab == 0 and not self.is_refreshing:
69+
# Try background refresh; if lock is busy, skip this tick
70+
acquired = self._refresh_lock.acquire(blocking=False)
71+
if not acquired:
72+
continue
73+
try:
74+
# Double-check state after acquiring lock
75+
if self.running and self.current_tab == 0 and not self.is_refreshing:
76+
self._background_refresh()
77+
finally:
78+
self._refresh_lock.release()
79+
80+
def _background_refresh(self):
81+
"""Refresh data without disrupting selection/menu state; redraw if still on recents."""
82+
self.is_refreshing = True
83+
# Do not redraw immediately to reduce flicker; header shows indicator on next paint
84+
85+
previous_index = self.selected_index
86+
try:
87+
if self._load_agent_runs():
88+
# Preserve selection but clamp to new list bounds
89+
if self.agent_runs:
90+
self.selected_index = max(0, min(previous_index, len(self.agent_runs) - 1))
91+
else:
92+
self.selected_index = 0
93+
finally:
94+
self.is_refreshing = False
95+
96+
# Redraw only if still on recents and app running
97+
if self.running and self.current_tab == 0:
98+
self._clear_and_redraw()
99+
46100
def _get_webapp_domain(self) -> str:
47101
"""Get the webapp domain based on environment."""
48102
return get_domain()
@@ -72,6 +126,10 @@ def _format_status_line(self, left_text: str) -> str:
72126
instructions_line = f"\033[90m{left_text}\033[0m"
73127
org_line = f"{purple_color}{org_name}{reset_color}"
74128

129+
# Append a subtle refresh indicator when a refresh is in progress
130+
if getattr(self, "is_refreshing", False):
131+
org_line += " \033[90m■ Refreshing…\033[0m"
132+
75133
return f"{instructions_line}\n{org_line}"
76134

77135
def _load_agent_runs(self) -> bool:
@@ -685,9 +743,17 @@ def _open_agent_details(self):
685743

686744
def _refresh(self):
687745
"""Refresh the agent runs list."""
746+
# Indicate refresh and redraw immediately so the user sees it
747+
self.is_refreshing = True
748+
self._clear_and_redraw()
749+
688750
if self._load_agent_runs():
689751
self.selected_index = 0 # Reset selection
690752

753+
# Clear refresh indicator and redraw with updated data
754+
self.is_refreshing = False
755+
self._clear_and_redraw()
756+
691757
def _clear_and_redraw(self):
692758
"""Clear screen and redraw everything."""
693759
# Move cursor to top and clear screen from cursor down

0 commit comments

Comments
 (0)