// This file is part of Deja-Vu. // // Deja-Vu is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Deja-Vu is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Deja-Vu. If not, see . // use color_eyre::Result; use ratatui::{ Frame, layout::{Alignment, Rect}, style::{Color, Style, Stylize}, text::{Line, Span}, widgets::{Block, Borders, Clear, Paragraph}, }; use tracing::info; use core::{ action::{Action, DiagResult}, components::Component, state::Mode, }; #[derive(Debug, Clone)] struct ProgressLine { name: String, text: String, result: DiagResult, running: bool, } impl ProgressLine { pub fn len_name(&self) -> usize { self.name.chars().count() } } #[derive(Default, Debug, Clone)] pub struct Progress { // command_tx: Option>, // config: Config, lines: Vec, mode: Mode, } impl Progress { #[must_use] pub fn new() -> Self { Self::default() } // fn register_action_handler(&mut self, tx: UnboundedSender) -> Result<()> { // self.command_tx = Some(tx); // Ok(()) // } // fn register_config_handler(&mut self, config: Config) -> Result<()> { // self.config = config; // Ok(()) // } } impl Component for Progress { fn update(&mut self, action: Action) -> Result> { match action { Action::DiagLineStart { text } => { info!("Caught Action::DiagLineStart {{ \"{}\" }}", &text); self.lines.push(ProgressLine { name: text, text: String::from("OK"), result: DiagResult::Pass, running: true, }); } Action::DiagLineUpdate { result, text } => { info!( "Caught Action::DiagLineUpdate {{ {}, \"{}\" }}", &result, &text ); if let Some(line) = self.lines.last_mut() { line.result = result; line.text = text; } } Action::DiagLineEnd { text } => { info!("Caught Action::DiagLineEnd {{ \"{}\" }}", &text); if let Some(line) = self.lines.last_mut() { line.running = false; } } Action::SetMode(mode) => { self.mode = mode; self.lines.clear(); } _ => {} }; Ok(None) } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.mode != Mode::BootScan { return Ok(()); } let mut body_text = Vec::with_capacity(20); // TODO: Needs fine tuning? body_text.push(Line::default()); // Add line(s) self.lines.iter().for_each(|line| { //.for_each(|(part, color)| spans.push(Span::styled(part, Style::default().fg(color)))); //Line::from(spans) let color = match line.result { DiagResult::Pass => Color::Green, DiagResult::Fail => Color::Red, DiagResult::Warn => Color::Yellow, }; let text = if line.running || line.text.is_empty() { String::from("...") } else { line.text.clone() }; let text = format!(" [ {text} ] "); let width = area.width as usize - line.len_name() - 1 - text.chars().count() - 7; // ' [ ]' let spans = vec![ Span::raw(format!("{} {:.