Re-added-again-added Mode::Home
Now lists tools on left and descriptions on the right
This commit is contained in:
2Shirt 2025-01-21 22:09:26 -08:00
parent de214dae2e
commit 408de46e73
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
7 changed files with 59 additions and 32 deletions

View file

@ -2,6 +2,12 @@
"app_title": "Deja-vu",
"clone_app_path": "C:/Program Files/Some Clone Tool/app.exe",
"keybindings": {
"Home": {
"<q>": "Quit",
"<Ctrl-d>": "Quit",
"<Ctrl-c>": "Quit",
"<Ctrl-z>": "Suspend"
},
"ScanDisks": {
"<q>": "Quit",
"<Ctrl-d>": "Quit",

View file

@ -20,6 +20,7 @@ use ratatui::{
widgets::{Block, Borders, Padding, Paragraph, Wrap},
};
use tokio::sync::mpsc::UnboundedSender;
use tracing::info;
use super::{state::StatefulList, Component};
use crate::{action::Action, config::Config, line::DVLine};

View file

@ -529,7 +529,7 @@ mod tests {
let c = Config::new()?;
assert_eq!(
c.keybindings
.get(&Mode::ScanDisks) // i.e. Home
.get(&Mode::Home) // i.e. Home
.unwrap()
.get(&parse_key_sequence("<q>").unwrap_or_default())
.unwrap(),

View file

@ -21,7 +21,7 @@ use crate::config;
lazy_static::lazy_static! {
pub static ref LOG_ENV: String = format!("{}_LOG_LEVEL", config::PROJECT_NAME);
pub static ref LOG_FILE: String = format!("{}.log", config::PROJECT_NAME);
pub static ref LOG_FILE: String = format!("{}.log", config::PROJECT_NAME.to_lowercase());
//pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME"));
}

View file

@ -25,8 +25,12 @@ use crate::system::{
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Mode {
// Clone
// Core
#[default]
Home,
Done,
Failed,
// Clone
ScanDisks,
InstallDrivers,
SelectDisks,
@ -36,9 +40,6 @@ pub enum Mode {
Clone,
SelectParts,
PostClone,
// Core
Done,
Failed,
// WinPE
PEMenu,
}

View file

@ -69,8 +69,7 @@ impl App {
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
let (action_tx, action_rx) = mpsc::unbounded_channel();
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
let mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
tasks.add(Task::ScanDisks);
let tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
Ok(Self {
// TUI
action_rx,
@ -91,9 +90,9 @@ impl App {
tick_rate,
// App
clone: CloneSettings::new(disk_list_arc),
cur_mode: Mode::ScanDisks,
cur_mode: Mode::default(),
list: StatefulList::default(),
prev_mode: Mode::ScanDisks,
prev_mode: Mode::default(),
selections: vec![None, None],
tasks,
})
@ -101,6 +100,7 @@ impl App {
pub fn prev_mode(&mut self) -> Option<Mode> {
let new_mode = match self.cur_mode {
Mode::Home => Some(Mode::Home),
Mode::Failed => Some(Mode::Failed),
Mode::Done => Some(Mode::Done),
Mode::SelectParts => Some(Mode::SelectParts),
@ -121,6 +121,7 @@ impl App {
pub fn next_mode(&mut self) -> Option<Mode> {
let new_mode = match self.cur_mode {
Mode::Home => Mode::ScanDisks,
Mode::InstallDrivers => Mode::ScanDisks,
Mode::ScanDisks => Mode::SelectDisks,
Mode::SelectDisks => Mode::SelectTableType,
@ -273,10 +274,7 @@ impl App {
}
let action_tx = self.action_tx.clone();
action_tx.send(Action::DisplayPopup(
popup::Type::Info,
String::from("Scanning Disks..."),
))?;
action_tx.send(Action::SetMode(Mode::ScanDisks))?;
loop {
self.handle_events(&mut tui).await?;
self.handle_actions(&mut tui)?;
@ -564,7 +562,7 @@ fn get_chunks(r: Rect) -> Vec<Rect> {
fn build_footer_string(cur_mode: Mode) -> String {
match cur_mode {
Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
Mode::Home | Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
String::from("(q) to quit")
}
Mode::SelectParts => String::from("(Enter) to select / (s) to start over / (q) to quit"),
@ -585,6 +583,9 @@ fn build_left_items(app: &App, cur_mode: Mode) -> (String, Vec<String>, Vec<Stri
let mut labels: Vec<String> = Vec::new();
let mut select_one = false;
match cur_mode {
Mode::Home => {
title = String::from("Home");
}
Mode::InstallDrivers => {
title = String::from("Install Drivers");
select_one = true;

View file

@ -56,8 +56,7 @@ impl Menu {
let exe_path = env::current_exe().expect("Failed to find main executable");
let contents = fs::read_to_string(exe_path.with_file_name("pe-menu.toml"))
.expect("Failed to load config file");
let mut menu_entries: Menu =
toml::from_str(&contents).expect("Failed to parse config file");
let mut menu: Menu = toml::from_str(&contents).expect("Failed to parse config file");
// Tools
let tool_config_path = exe_path.parent().unwrap().join("menu_entries");
@ -67,14 +66,14 @@ impl Menu {
.filter_map(Result::ok)
.collect();
entries.sort();
for entry in entries {
entries.iter().for_each(|entry| {
let contents = fs::read_to_string(&entry).expect("Failed to read tool config file");
let tool: Tool = toml::from_str(&contents).expect("Failed to parse tool config file");
menu_entries.tools.push(tool);
}
menu.tools.push(tool);
});
// Done
menu_entries
menu
}
}
@ -111,7 +110,6 @@ impl App {
let (action_tx, action_rx) = mpsc::unbounded_channel();
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
let mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
tasks.add(Task::ScanDisks);
Ok(Self {
// TUI
action_rx,
@ -133,7 +131,7 @@ impl App {
// App
list: StatefulList::default(),
menu: Menu::load(),
mode: Mode::PEMenu,
mode: Mode::default(),
selections: vec![None, None],
})
}
@ -156,6 +154,7 @@ impl App {
}
let action_tx = self.action_tx.clone();
action_tx.send(Action::SetMode(Mode::PEMenu))?;
loop {
self.handle_events(&mut tui).await?;
self.handle_actions(&mut tui)?;
@ -240,11 +239,13 @@ impl App {
Action::Process => {
if let Some(index) = self.list.selected() {
//TODO: Run selected tool?
info!("Run tool at index: {index}");
}
}
Action::Resize(w, h) => self.handle_resize(tui, w, h)?,
Action::Render => self.render(tui)?,
Action::SetMode(_) => {
Action::SetMode(mode) => {
self.mode = mode;
self.action_tx
.send(Action::UpdateFooter(String::from("(Enter) to select")))?;
let (title, labels, items, select_one) = build_left_items(self);
@ -254,6 +255,11 @@ impl App {
self.action_tx
.send(Action::UpdateRight(labels, start, items))?;
}
Action::UpdateFooter(_)
| Action::UpdateLeft(_, _, _, _)
| Action::UpdateRight(_, _, _) => {
info!("Processing Action: {:?}", action);
}
_ => {}
}
for component in &mut self.components {
@ -348,27 +354,39 @@ fn get_chunks(r: Rect) -> Vec<Rect> {
fn build_left_items(app: &App) -> (String, Vec<String>, Vec<String>, bool) {
let title = String::from("Tools");
let labels = vec![String::new(), String::new()];
let items = app
.menu
.tools
.iter()
.map(|tool| tool.name.clone())
.collect();
let labels: Vec<String> = Vec::new();
(title, labels, items, true)
(title, labels, items, false)
}
fn build_right_items(app: &App) -> (Vec<Vec<DVLine>>, usize, Vec<Vec<DVLine>>) {
let items = vec![app
let labels: Vec<Vec<DVLine>> = Vec::new();
let items = app
.menu
.tools
.iter()
.map(|item| DVLine {
line_parts: vec![item.description.clone()],
line_colors: vec![Color::Reset],
.map(|entry| {
vec![
DVLine {
line_parts: vec![entry.name.clone()],
line_colors: vec![Color::Cyan],
},
DVLine {
line_parts: vec![String::new()],
line_colors: vec![Color::Reset],
},
DVLine {
line_parts: vec![entry.description.clone()],
line_colors: vec![Color::Reset],
},
]
})
.collect()];
let labels: Vec<Vec<DVLine>> = Vec::new();
.collect();
let start_index = 0;
(labels, start_index, items)
}