This commit is contained in:
2Shirt 2025-01-15 19:17:05 -08:00
parent 9d6fa954b2
commit 353f2d5570
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
5 changed files with 152 additions and 21 deletions

View file

@ -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<Disk>),
UpdateLeft(Vec<DVLine>, Vec<String>),
UpdateRight(Vec<DVLine>, Vec<String>),
// Screens
DismissPopup,
DisplayPopup(Type, String),

View file

@ -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<Rect> {
// Done
chunks
}
fn get_right_headers(prev_mode: Mode, cur_mode: Mode) -> Vec<DVLine> {
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
}

View file

@ -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<UnboundedSender<Action>>,
config: Config,
cur_mode: Mode,
list_disks: StatefulList<Disk>,
list_parts: StatefulList<Partition>,
list_desc: StatefulList<Vec<text::Line<'a>>>,
list_item: StatefulList<Vec<text::Line<'a>>>,
prev_mode: Mode,
selected_disks: Vec<Option<usize>>,
selections: Vec<Option<usize>>,
table_type: Option<PartitionTableType>,
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<Option<Action>> {
let _ = key; // to appease clippy
Ok(None)
@ -149,9 +144,16 @@ impl Component for Right {
}
}
}
Action::UpdateRight(new_descs, new_items) => {
let lines: Vec<text::Line> = new_descs.iter().map(|d| d.as_line()).collect();
let items: Vec<text::Line> = 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()))));

37
deja_vu/src/line.rs Normal file
View file

@ -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 <https://www.gnu.org/licenses/>.
//
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<String>,
pub line_colors: Vec<Color>,
}
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)
}
}

View file

@ -25,6 +25,7 @@ mod cli;
mod components;
mod config;
mod errors;
mod line;
mod logging;
mod state;
mod system;