feat(frontend): Add generations counter to inform frontends when a list should be re-rendered.

This commit is contained in:
2026-03-14 11:47:27 -04:00
parent e5c875389c
commit a27d529fa7
2 changed files with 15 additions and 1 deletions

View File

@@ -72,6 +72,10 @@ pub struct ViewState {
pub total_items: usize,
pub total_filtered: usize,
pub mode: Mode,
/// Monotonically increasing counter. Each call to
/// `build_view_state()` bumps this, so frontends can
/// detect duplicate broadcasts and skip redundant redraws.
pub generation: u64,
}
/// A single item in the current viewport window. Has the

View File

@@ -82,6 +82,7 @@ async fn run_inner(
let mut event_stream = EventStream::new();
let mut mode = Mode::Insert;
let mut pending = PendingKey::None;
let mut last_generation: u64 = 0;
loop {
if let Some(ref vs) = view_state {
@@ -118,6 +119,11 @@ async fn run_inner(
menu_event = event_rx.recv() => {
match menu_event {
Ok(MenuEvent::StateChanged(vs)) => {
// Skip duplicate broadcasts
if vs.generation == last_generation {
continue;
}
last_generation = vs.generation;
// Sync filter text from core. Local keystrokes
// update filter_text immediately for responsiveness,
// but if core pushes a different value (e.g. IPC
@@ -135,7 +141,9 @@ async fn run_inner(
Ok(MenuEvent::Selected(_) | MenuEvent::Quicklist(_) | MenuEvent::Cancelled) => {
break;
}
Err(broadcast::error::RecvError::Lagged(_)) => {}
Err(broadcast::error::RecvError::Lagged(n)) => {
tracing::warn!(skipped = n, "TUI fell behind on state broadcasts");
}
Err(broadcast::error::RecvError::Closed) => {
break;
}
@@ -340,6 +348,7 @@ mod tests {
total_items: 5,
total_filtered: 3,
mode: Mode::Insert,
generation: 1,
}
}
@@ -811,6 +820,7 @@ mod tests {
total_items: 0,
total_filtered: 0,
mode: Mode::Insert,
generation: 1,
};
let backend = render_to_backend(30, 4, &vs, "");
let prompt = line_text(&backend, 0);