feat(tui): Phase 2 Issue List + MR List screens

Implement state, action, and view layers for both list screens:
- Issue List: keyset pagination, snapshot fence, filter DSL, label aggregation
- MR List: mirrors Issue pattern with draft/reviewer/target branch filters
- Migration 027: covering indexes for TUI list screen queries
- Updated Msg types to use typed Page structs instead of raw Vec<Row>
- 303 tests passing, clippy clean

Beads: bd-3ei1, bd-2kr0, bd-3pm2
This commit is contained in:
teernisse
2026-02-18 13:06:06 -05:00
parent c5b7f4c864
commit 90c8b43267
33 changed files with 7850 additions and 483 deletions

View File

@@ -24,7 +24,7 @@ pub mod sync;
pub mod timeline;
pub mod who;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use crate::message::Screen;
@@ -80,6 +80,8 @@ impl LoadState {
#[derive(Debug, Default)]
pub struct ScreenLoadStateMap {
map: HashMap<Screen, LoadState>,
/// Screens that have had a load state set at least once.
visited: HashSet<Screen>,
}
impl ScreenLoadStateMap {
@@ -94,6 +96,7 @@ impl ScreenLoadStateMap {
///
/// Setting to `Idle` removes the entry to prevent map growth.
pub fn set(&mut self, screen: Screen, state: LoadState) {
self.visited.insert(screen.clone());
if state == LoadState::Idle {
self.map.remove(&screen);
} else {
@@ -101,6 +104,12 @@ impl ScreenLoadStateMap {
}
}
/// Whether this screen has ever had a load initiated.
#[must_use]
pub fn was_visited(&self, screen: &Screen) -> bool {
self.visited.contains(screen)
}
/// Whether any screen is currently loading.
#[must_use]
pub fn any_loading(&self) -> bool {