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
74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
#![allow(dead_code)] // Phase 1: methods consumed as screens are implemented
|
|
|
|
//! Full FrankenTUI Model implementation for the lore TUI.
|
|
//!
|
|
//! LoreApp is the central coordinator: it owns all state, dispatches
|
|
//! messages through a 5-stage key pipeline, records crash context
|
|
//! breadcrumbs, manages async tasks via the supervisor, and routes
|
|
//! view() to per-screen render functions.
|
|
|
|
mod tests;
|
|
mod update;
|
|
|
|
use crate::clock::{Clock, SystemClock};
|
|
use crate::commands::{CommandRegistry, build_registry};
|
|
use crate::crash_context::CrashContext;
|
|
use crate::db::DbManager;
|
|
use crate::message::InputMode;
|
|
use crate::navigation::NavigationStack;
|
|
use crate::state::AppState;
|
|
use crate::task_supervisor::TaskSupervisor;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// LoreApp
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Root model for the lore TUI.
|
|
///
|
|
/// Owns all state and implements the FrankenTUI Model trait. The
|
|
/// update() method is the single entry point for all state transitions.
|
|
pub struct LoreApp {
|
|
pub state: AppState,
|
|
pub navigation: NavigationStack,
|
|
pub supervisor: TaskSupervisor,
|
|
pub crash_context: CrashContext,
|
|
pub command_registry: CommandRegistry,
|
|
pub input_mode: InputMode,
|
|
pub clock: Box<dyn Clock>,
|
|
pub db: Option<DbManager>,
|
|
}
|
|
|
|
impl LoreApp {
|
|
/// Create a new LoreApp with default state.
|
|
///
|
|
/// Uses a real system clock and no DB connection (set separately).
|
|
#[must_use]
|
|
pub fn new() -> Self {
|
|
Self {
|
|
state: AppState::default(),
|
|
navigation: NavigationStack::new(),
|
|
supervisor: TaskSupervisor::new(),
|
|
crash_context: CrashContext::new(),
|
|
command_registry: build_registry(),
|
|
input_mode: InputMode::Normal,
|
|
clock: Box::new(SystemClock),
|
|
db: None,
|
|
}
|
|
}
|
|
|
|
/// Create a LoreApp for testing with a custom clock.
|
|
#[cfg(test)]
|
|
fn with_clock(clock: Box<dyn Clock>) -> Self {
|
|
Self {
|
|
clock,
|
|
..Self::new()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for LoreApp {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|