feat(tui): Phase 3 power features — Who, Search, Timeline, Trace, File History screens
Complete TUI Phase 3 implementation with all 5 power feature screens: - Who screen: 5 modes (expert/workload/reviews/active/overlap) with mode tabs, input bar, result rendering, and hint bar - Search screen: full-text search with result list and scoring display - Timeline screen: chronological event feed with time-relative display - Trace screen: file provenance chains with expand/collapse, rename tracking, and linked issues/discussions - File History screen: per-file MR timeline with rename chain display and discussion snippets Also includes: - Command palette overlay (fuzzy search) - Bootstrap screen (initial sync flow) - Action layer split from monolithic action.rs to per-screen modules - Entity and render cache infrastructure - Shared who_types module in core crate - All screens wired into view/mod.rs dispatch - 597 tests passing, clippy clean (pedantic + nursery), fmt clean
This commit is contained in:
160
crates/lore-tui/src/state/bootstrap.rs
Normal file
160
crates/lore-tui/src/state/bootstrap.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
#![allow(dead_code)] // Phase 2.5: consumed by Bootstrap screen
|
||||
|
||||
//! Bootstrap screen state.
|
||||
//!
|
||||
//! Handles first-launch and empty-database scenarios. The schema
|
||||
//! preflight runs before the TUI event loop; the bootstrap screen
|
||||
//! guides users to sync when no data is available.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DataReadiness
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Result of checking whether the database has enough data to show the TUI.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DataReadiness {
|
||||
/// Database has at least one issue.
|
||||
pub has_issues: bool,
|
||||
/// Database has at least one merge request.
|
||||
pub has_mrs: bool,
|
||||
/// Database has at least one search document.
|
||||
pub has_documents: bool,
|
||||
/// Current schema version from the schema_version table.
|
||||
pub schema_version: i32,
|
||||
}
|
||||
|
||||
impl DataReadiness {
|
||||
/// Whether the database has any entity data at all.
|
||||
#[must_use]
|
||||
pub fn has_any_data(&self) -> bool {
|
||||
self.has_issues || self.has_mrs
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SchemaCheck
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Result of schema version validation.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum SchemaCheck {
|
||||
/// Schema is at or above the minimum required version.
|
||||
Compatible { version: i32 },
|
||||
/// No database or no schema_version table found.
|
||||
NoDB,
|
||||
/// Schema exists but is too old for this TUI version.
|
||||
Incompatible { found: i32, minimum: i32 },
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// BootstrapState
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// State for the Bootstrap screen.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BootstrapState {
|
||||
/// Whether a data readiness check has completed.
|
||||
pub readiness: Option<DataReadiness>,
|
||||
/// Whether the user has initiated a sync from the bootstrap screen.
|
||||
pub sync_started: bool,
|
||||
}
|
||||
|
||||
impl BootstrapState {
|
||||
/// Apply a data readiness result.
|
||||
pub fn apply_readiness(&mut self, readiness: DataReadiness) {
|
||||
self.readiness = Some(readiness);
|
||||
}
|
||||
|
||||
/// Whether we have data (and should auto-transition to Dashboard).
|
||||
#[must_use]
|
||||
pub fn should_transition_to_dashboard(&self) -> bool {
|
||||
self.readiness
|
||||
.as_ref()
|
||||
.is_some_and(DataReadiness::has_any_data)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_data_readiness_has_any_data() {
|
||||
let empty = DataReadiness {
|
||||
has_issues: false,
|
||||
has_mrs: false,
|
||||
has_documents: false,
|
||||
schema_version: 26,
|
||||
};
|
||||
assert!(!empty.has_any_data());
|
||||
|
||||
let with_issues = DataReadiness {
|
||||
has_issues: true,
|
||||
..empty.clone()
|
||||
};
|
||||
assert!(with_issues.has_any_data());
|
||||
|
||||
let with_mrs = DataReadiness {
|
||||
has_mrs: true,
|
||||
..empty
|
||||
};
|
||||
assert!(with_mrs.has_any_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_schema_check_variants() {
|
||||
let compat = SchemaCheck::Compatible { version: 26 };
|
||||
assert!(matches!(compat, SchemaCheck::Compatible { version: 26 }));
|
||||
|
||||
let no_db = SchemaCheck::NoDB;
|
||||
assert!(matches!(no_db, SchemaCheck::NoDB));
|
||||
|
||||
let incompat = SchemaCheck::Incompatible {
|
||||
found: 10,
|
||||
minimum: 20,
|
||||
};
|
||||
assert!(matches!(
|
||||
incompat,
|
||||
SchemaCheck::Incompatible {
|
||||
found: 10,
|
||||
minimum: 20
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bootstrap_state_default() {
|
||||
let state = BootstrapState::default();
|
||||
assert!(state.readiness.is_none());
|
||||
assert!(!state.sync_started);
|
||||
assert!(!state.should_transition_to_dashboard());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bootstrap_state_apply_readiness_empty() {
|
||||
let mut state = BootstrapState::default();
|
||||
state.apply_readiness(DataReadiness {
|
||||
has_issues: false,
|
||||
has_mrs: false,
|
||||
has_documents: false,
|
||||
schema_version: 26,
|
||||
});
|
||||
assert!(!state.should_transition_to_dashboard());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bootstrap_state_apply_readiness_with_data() {
|
||||
let mut state = BootstrapState::default();
|
||||
state.apply_readiness(DataReadiness {
|
||||
has_issues: true,
|
||||
has_mrs: false,
|
||||
has_documents: false,
|
||||
schema_version: 26,
|
||||
});
|
||||
assert!(state.should_transition_to_dashboard());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user