diff --git a/deja_vu/src/action.rs b/deja_vu/src/action.rs index 29b4fa5..1695123 100644 --- a/deja_vu/src/action.rs +++ b/deja_vu/src/action.rs @@ -18,6 +18,7 @@ use strum::Display; use crate::{ components::popup::Type, + line::DVLine, state::Mode, system::{ disk::{Disk, PartitionTableType}, @@ -35,6 +36,8 @@ pub enum Action { SelectDriver(Driver), SelectTableType(PartitionTableType), UpdateDiskList(Vec), + UpdateLeft(Vec, Vec), + UpdateRight(Vec, Vec), // Screens DismissPopup, DisplayPopup(Type, String), diff --git a/deja_vu/src/app.rs b/deja_vu/src/app.rs index 4f3dfa7..61f017f 100644 --- a/deja_vu/src/app.rs +++ b/deja_vu/src/app.rs @@ -25,6 +25,7 @@ use crossterm::event::KeyEvent; use ratatui::{ layout::{Constraint, Direction, Layout}, prelude::Rect, + style::Color, }; use tokio::sync::mpsc; use tracing::{debug, info}; @@ -35,9 +36,11 @@ use crate::{ footer::Footer, fps::FpsCounter, left::Left, popup, right::Right, title::Title, Component, }, config::Config, + line::DVLine, state::{CloneSettings, Mode}, system::{ boot, + cpu::get_cpu_name, diskpart::build_dest_format_script, drivers::{self}, }, @@ -240,7 +243,6 @@ impl App { String::from("COMPLETE\n\n\nThank you for using this tool!"), ))?; } - _ => {} } Ok(()) } @@ -488,3 +490,68 @@ fn get_chunks(r: Rect) -> Vec { // Done chunks } + +fn get_right_headers(prev_mode: Mode, cur_mode: Mode) -> Vec { + let mut headers = Vec::new(); + + // Main header + match (prev_mode, cur_mode) { + (_, Mode::InstallDrivers) => headers.push(DVLine { + line_parts: vec![String::from("CPU"), get_cpu_name()], + line_colors: vec![Color::Cyan, Color::Reset], + }), + (_, Mode::SelectDisks | Mode::SelectTableType) + | (Mode::SelectDisks | Mode::SelectTableType, Mode::Confirm) => { + // Source Disk Details + headers.push(DVLine { + line_parts: vec![String::from("Source")], + line_colors: vec![Color::Cyan], + }); + headers.push(DVLine { + line_parts: vec![String::new()], + line_colors: vec![Color::Reset], + }); + headers.push(DVLine { + line_parts: vec![String::new()], + line_colors: vec![Color::Reset], + }); + headers.push(DVLine { + line_parts: vec![format!( + "{:<8} {:>11} {:<4} {:<4} {}", + "Disk ID", "Size", "Conn", "Type", "Model (Serial)" + )], + line_colors: vec![Color::Green], + }); + } + _ => {} + } + + // First selection + match (prev_mode, cur_mode) { + (_, Mode::SelectDisks | Mode::SelectTableType) + | (Mode::SelectDisks | Mode::SelectTableType, Mode::Confirm) => headers.push(DVLine { + line_parts: vec![String::from("Source"), get_cpu_name()], + line_colors: vec![Color::Cyan, Color::Reset], + }), + (Mode::SelectParts, Mode::Confirm) => { + headers.push(DVLine { + line_parts: vec![String::from("Dest")], + line_colors: vec![Color::Cyan], + }); + // Disk details + // Part details + } + _ => {} + }; + // Source + // SelectDisks + // SelectTableType + // Confirm (for above ^) + // Dest + // SelectParts + // (SelectParts, Confirm) + + // Second selection + + headers +} diff --git a/deja_vu/src/components/right.rs b/deja_vu/src/components/right.rs index 1e1fc0f..b707fe9 100644 --- a/deja_vu/src/components/right.rs +++ b/deja_vu/src/components/right.rs @@ -23,40 +23,35 @@ use tokio::sync::mpsc::UnboundedSender; use tracing::info; use super::{state::StatefulList, Component}; -use crate::{ - action::Action, - config::Config, - state::Mode, - system::{ - cpu::get_cpu_name, - disk::{Disk, Partition, PartitionTableType}, - }, -}; +use crate::{action::Action, config::Config, state::Mode}; #[derive(Default)] -pub struct Right { +pub struct Right<'a> { command_tx: Option>, config: Config, cur_mode: Mode, - list_disks: StatefulList, - list_parts: StatefulList, + list_desc: StatefulList>>, + list_item: StatefulList>>, prev_mode: Mode, - selected_disks: Vec>, selections: Vec>, - table_type: Option, + title: String, } -impl Right { +impl Right<'_> { pub fn new() -> Self { Self { - selected_disks: vec![None, None], selections: vec![None, None], + title: String::from("Info"), ..Default::default() } } + + pub fn set_title(&mut self, new_title: &str) { + self.title = String::from(new_title); + } } -impl Component for Right { +impl Component for Right<'_> { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { let _ = key; // to appease clippy Ok(None) @@ -149,9 +144,16 @@ impl Component for Right { } } } + Action::UpdateRight(new_descs, new_items) => { + let lines: Vec = new_descs.iter().map(|d| d.as_line()).collect(); + let items: Vec = new_items.iter().map(|p| text::Line::from(p.as_str())).collect(); + self.list_desc.set_items(lines); + // TODO / FIXME + } _ => {} } - Ok(None) + Ok(None)E0277 + body_text.push(Line::from(Span::raw(format!("CPU: {}", get_cpu_name())))); } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { @@ -161,13 +163,34 @@ impl Component for Right { .areas(area); // Title - let title_text = String::from("Info"); - let title = Paragraph::new(Line::from(title_text).centered()) + let title = Paragraph::new(Line::from(self.title).centered()) .block(Block::default().borders(Borders::NONE)); frame.render_widget(title, title_area); // Body let mut body_text = Vec::new(); + if let Some(header) = self.list_desc.get(0) { + header.iter().map(|line| body_text.push(line)); + } + if let Some(first_index) = self.selections[0] { + if let Some(first_desc) = self.list_desc.get(first_index + 1) { + first_desc.iter().map(|line| body_text.push(line)); + } + if let Some(first_item) = self.list_item.get(first_index) { + first_item.iter().map(|line| body_text.push(line)); + } + } + if let Some(second_index) = self.selections[1] { + if let Some(second_desc) = self.list_desc.get(second_index + 1) { + second_desc.iter().map(|line| body_text.push(line)); + } + if let Some(second_item) = self.list_item.get(second_index) { + second_item.iter().map(|line| body_text.push(line)); + } + } + + // Body (Old) + let mut body_text = Vec::new(); match (self.prev_mode, self.cur_mode) { (_, Mode::InstallDrivers) => { body_text.push(Line::from(Span::raw(format!("CPU: {}", get_cpu_name())))); diff --git a/deja_vu/src/line.rs b/deja_vu/src/line.rs new file mode 100644 index 0000000..a5f5d1b --- /dev/null +++ b/deja_vu/src/line.rs @@ -0,0 +1,37 @@ +// 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 ratatui::{ + style::{Color, Style}, + text::{Line, Span}, +}; +use serde::{Deserialize, Serialize}; +use std::iter::zip; + +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct DVLine { + pub line_parts: Vec, + pub line_colors: Vec, +} + +impl DVLine { + /// Convert to Line with colored span(s) + pub fn as_line(&self) -> Line { + let mut spans = Vec::new(); + zip(self.line_parts.clone(), self.line_colors.clone()) + .map(|(part, color)| spans.push(Span::styled(part, Style::default().fg(color)))); + Line::from(spans) + } +} diff --git a/deja_vu/src/main.rs b/deja_vu/src/main.rs index 085974a..c5e3a71 100644 --- a/deja_vu/src/main.rs +++ b/deja_vu/src/main.rs @@ -25,6 +25,7 @@ mod cli; mod components; mod config; mod errors; +mod line; mod logging; mod state; mod system;