Show loading state when @ search results are pending (#3061)

## Summary
- allow selection popups to specify their empty state message
- show a "loading..." placeholder in the file search popup while matches
are pending
- update other popup call sites to continue using a "no matches" message

## Testing
- just fmt
- just fix -p codex-tui
- cargo test -p codex-tui

------
https://chatgpt.com/codex/tasks/task_i_68b73e956e90832caf4d04a75fcc9c46
This commit is contained in:
Jeremy Rose
2025-09-02 16:38:43 -07:00
committed by GitHub
parent 578ff09e17
commit 3baccba0ac
4 changed files with 34 additions and 8 deletions

View File

@@ -195,7 +195,15 @@ impl WidgetRef for CommandPopup {
}) })
.collect() .collect()
}; };
render_rows(area, buf, &rows_all, &self.state, MAX_POPUP_ROWS, false); render_rows(
area,
buf,
&rows_all,
&self.state,
MAX_POPUP_ROWS,
false,
"no matches",
);
} }
} }

View File

@@ -132,11 +132,20 @@ impl WidgetRef for &FileSearchPopup {
.collect() .collect()
}; };
if self.waiting && rows_all.is_empty() { let empty_message = if self.waiting {
// Render a minimal waiting stub using the shared renderer (no rows -> "no matches"). "loading..."
render_rows(area, buf, &[], &self.state, MAX_POPUP_ROWS, false);
} else { } else {
render_rows(area, buf, &rows_all, &self.state, MAX_POPUP_ROWS, false); "no matches"
} };
render_rows(
area,
buf,
&rows_all,
&self.state,
MAX_POPUP_ROWS,
false,
empty_message,
);
} }
} }

View File

@@ -222,7 +222,15 @@ impl BottomPaneView for ListSelectionView {
}) })
.collect(); .collect();
if rows_area.height > 0 { if rows_area.height > 0 {
render_rows(rows_area, buf, &rows, &self.state, MAX_POPUP_ROWS, true); render_rows(
rows_area,
buf,
&rows,
&self.state,
MAX_POPUP_ROWS,
true,
"no matches",
);
} }
if let Some(hint) = &self.footer_hint { if let Some(hint) = &self.footer_hint {

View File

@@ -36,11 +36,12 @@ pub(crate) fn render_rows(
state: &ScrollState, state: &ScrollState,
max_results: usize, max_results: usize,
_dim_non_selected: bool, _dim_non_selected: bool,
empty_message: &str,
) { ) {
let mut rows: Vec<Row> = Vec::new(); let mut rows: Vec<Row> = Vec::new();
if rows_all.is_empty() { if rows_all.is_empty() {
rows.push(Row::new(vec![Cell::from(Line::from( rows.push(Row::new(vec![Cell::from(Line::from(
"no matches".dim().italic(), empty_message.dim().italic(),
))])); ))]));
} else { } else {
let max_rows_from_area = area.height as usize; let max_rows_from_area = area.height as usize;