WIP
Re-added-again-added Mode::Home Now lists tools on left and descriptions on the right
This commit is contained in:
parent
de214dae2e
commit
408de46e73
7 changed files with 59 additions and 32 deletions
|
|
@ -2,6 +2,12 @@
|
||||||
"app_title": "Deja-vu",
|
"app_title": "Deja-vu",
|
||||||
"clone_app_path": "C:/Program Files/Some Clone Tool/app.exe",
|
"clone_app_path": "C:/Program Files/Some Clone Tool/app.exe",
|
||||||
"keybindings": {
|
"keybindings": {
|
||||||
|
"Home": {
|
||||||
|
"<q>": "Quit",
|
||||||
|
"<Ctrl-d>": "Quit",
|
||||||
|
"<Ctrl-c>": "Quit",
|
||||||
|
"<Ctrl-z>": "Suspend"
|
||||||
|
},
|
||||||
"ScanDisks": {
|
"ScanDisks": {
|
||||||
"<q>": "Quit",
|
"<q>": "Quit",
|
||||||
"<Ctrl-d>": "Quit",
|
"<Ctrl-d>": "Quit",
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ use ratatui::{
|
||||||
widgets::{Block, Borders, Padding, Paragraph, Wrap},
|
widgets::{Block, Borders, Padding, Paragraph, Wrap},
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use super::{state::StatefulList, Component};
|
use super::{state::StatefulList, Component};
|
||||||
use crate::{action::Action, config::Config, line::DVLine};
|
use crate::{action::Action, config::Config, line::DVLine};
|
||||||
|
|
|
||||||
|
|
@ -529,7 +529,7 @@ mod tests {
|
||||||
let c = Config::new()?;
|
let c = Config::new()?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
c.keybindings
|
c.keybindings
|
||||||
.get(&Mode::ScanDisks) // i.e. Home
|
.get(&Mode::Home) // i.e. Home
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&parse_key_sequence("<q>").unwrap_or_default())
|
.get(&parse_key_sequence("<q>").unwrap_or_default())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ use crate::config;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref LOG_ENV: String = format!("{}_LOG_LEVEL", config::PROJECT_NAME);
|
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"));
|
//pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,12 @@ use crate::system::{
|
||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
// Clone
|
// Core
|
||||||
#[default]
|
#[default]
|
||||||
|
Home,
|
||||||
|
Done,
|
||||||
|
Failed,
|
||||||
|
// Clone
|
||||||
ScanDisks,
|
ScanDisks,
|
||||||
InstallDrivers,
|
InstallDrivers,
|
||||||
SelectDisks,
|
SelectDisks,
|
||||||
|
|
@ -36,9 +40,6 @@ pub enum Mode {
|
||||||
Clone,
|
Clone,
|
||||||
SelectParts,
|
SelectParts,
|
||||||
PostClone,
|
PostClone,
|
||||||
// Core
|
|
||||||
Done,
|
|
||||||
Failed,
|
|
||||||
// WinPE
|
// WinPE
|
||||||
PEMenu,
|
PEMenu,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,7 @@ impl App {
|
||||||
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
|
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
|
||||||
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
||||||
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
|
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
|
||||||
let mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
|
let tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
|
||||||
tasks.add(Task::ScanDisks);
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
// TUI
|
// TUI
|
||||||
action_rx,
|
action_rx,
|
||||||
|
|
@ -91,9 +90,9 @@ impl App {
|
||||||
tick_rate,
|
tick_rate,
|
||||||
// App
|
// App
|
||||||
clone: CloneSettings::new(disk_list_arc),
|
clone: CloneSettings::new(disk_list_arc),
|
||||||
cur_mode: Mode::ScanDisks,
|
cur_mode: Mode::default(),
|
||||||
list: StatefulList::default(),
|
list: StatefulList::default(),
|
||||||
prev_mode: Mode::ScanDisks,
|
prev_mode: Mode::default(),
|
||||||
selections: vec![None, None],
|
selections: vec![None, None],
|
||||||
tasks,
|
tasks,
|
||||||
})
|
})
|
||||||
|
|
@ -101,6 +100,7 @@ impl App {
|
||||||
|
|
||||||
pub fn prev_mode(&mut self) -> Option<Mode> {
|
pub fn prev_mode(&mut self) -> Option<Mode> {
|
||||||
let new_mode = match self.cur_mode {
|
let new_mode = match self.cur_mode {
|
||||||
|
Mode::Home => Some(Mode::Home),
|
||||||
Mode::Failed => Some(Mode::Failed),
|
Mode::Failed => Some(Mode::Failed),
|
||||||
Mode::Done => Some(Mode::Done),
|
Mode::Done => Some(Mode::Done),
|
||||||
Mode::SelectParts => Some(Mode::SelectParts),
|
Mode::SelectParts => Some(Mode::SelectParts),
|
||||||
|
|
@ -121,6 +121,7 @@ impl App {
|
||||||
|
|
||||||
pub fn next_mode(&mut self) -> Option<Mode> {
|
pub fn next_mode(&mut self) -> Option<Mode> {
|
||||||
let new_mode = match self.cur_mode {
|
let new_mode = match self.cur_mode {
|
||||||
|
Mode::Home => Mode::ScanDisks,
|
||||||
Mode::InstallDrivers => Mode::ScanDisks,
|
Mode::InstallDrivers => Mode::ScanDisks,
|
||||||
Mode::ScanDisks => Mode::SelectDisks,
|
Mode::ScanDisks => Mode::SelectDisks,
|
||||||
Mode::SelectDisks => Mode::SelectTableType,
|
Mode::SelectDisks => Mode::SelectTableType,
|
||||||
|
|
@ -273,10 +274,7 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
let action_tx = self.action_tx.clone();
|
let action_tx = self.action_tx.clone();
|
||||||
action_tx.send(Action::DisplayPopup(
|
action_tx.send(Action::SetMode(Mode::ScanDisks))?;
|
||||||
popup::Type::Info,
|
|
||||||
String::from("Scanning Disks..."),
|
|
||||||
))?;
|
|
||||||
loop {
|
loop {
|
||||||
self.handle_events(&mut tui).await?;
|
self.handle_events(&mut tui).await?;
|
||||||
self.handle_actions(&mut tui)?;
|
self.handle_actions(&mut tui)?;
|
||||||
|
|
@ -564,7 +562,7 @@ fn get_chunks(r: Rect) -> Vec<Rect> {
|
||||||
|
|
||||||
fn build_footer_string(cur_mode: Mode) -> String {
|
fn build_footer_string(cur_mode: Mode) -> String {
|
||||||
match cur_mode {
|
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")
|
String::from("(q) to quit")
|
||||||
}
|
}
|
||||||
Mode::SelectParts => String::from("(Enter) to select / (s) to start over / (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 labels: Vec<String> = Vec::new();
|
||||||
let mut select_one = false;
|
let mut select_one = false;
|
||||||
match cur_mode {
|
match cur_mode {
|
||||||
|
Mode::Home => {
|
||||||
|
title = String::from("Home");
|
||||||
|
}
|
||||||
Mode::InstallDrivers => {
|
Mode::InstallDrivers => {
|
||||||
title = String::from("Install Drivers");
|
title = String::from("Install Drivers");
|
||||||
select_one = true;
|
select_one = true;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ impl Menu {
|
||||||
let exe_path = env::current_exe().expect("Failed to find main executable");
|
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"))
|
let contents = fs::read_to_string(exe_path.with_file_name("pe-menu.toml"))
|
||||||
.expect("Failed to load config file");
|
.expect("Failed to load config file");
|
||||||
let mut menu_entries: Menu =
|
let mut menu: Menu = toml::from_str(&contents).expect("Failed to parse config file");
|
||||||
toml::from_str(&contents).expect("Failed to parse config file");
|
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
let tool_config_path = exe_path.parent().unwrap().join("menu_entries");
|
let tool_config_path = exe_path.parent().unwrap().join("menu_entries");
|
||||||
|
|
@ -67,14 +66,14 @@ impl Menu {
|
||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
.collect();
|
.collect();
|
||||||
entries.sort();
|
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 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");
|
let tool: Tool = toml::from_str(&contents).expect("Failed to parse tool config file");
|
||||||
menu_entries.tools.push(tool);
|
menu.tools.push(tool);
|
||||||
}
|
});
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
menu_entries
|
menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +110,6 @@ impl App {
|
||||||
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
||||||
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
|
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
|
||||||
let mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
|
let mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
|
||||||
tasks.add(Task::ScanDisks);
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
// TUI
|
// TUI
|
||||||
action_rx,
|
action_rx,
|
||||||
|
|
@ -133,7 +131,7 @@ impl App {
|
||||||
// App
|
// App
|
||||||
list: StatefulList::default(),
|
list: StatefulList::default(),
|
||||||
menu: Menu::load(),
|
menu: Menu::load(),
|
||||||
mode: Mode::PEMenu,
|
mode: Mode::default(),
|
||||||
selections: vec![None, None],
|
selections: vec![None, None],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +154,7 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
let action_tx = self.action_tx.clone();
|
let action_tx = self.action_tx.clone();
|
||||||
|
action_tx.send(Action::SetMode(Mode::PEMenu))?;
|
||||||
loop {
|
loop {
|
||||||
self.handle_events(&mut tui).await?;
|
self.handle_events(&mut tui).await?;
|
||||||
self.handle_actions(&mut tui)?;
|
self.handle_actions(&mut tui)?;
|
||||||
|
|
@ -240,11 +239,13 @@ impl App {
|
||||||
Action::Process => {
|
Action::Process => {
|
||||||
if let Some(index) = self.list.selected() {
|
if let Some(index) = self.list.selected() {
|
||||||
//TODO: Run selected tool?
|
//TODO: Run selected tool?
|
||||||
|
info!("Run tool at index: {index}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::Resize(w, h) => self.handle_resize(tui, w, h)?,
|
Action::Resize(w, h) => self.handle_resize(tui, w, h)?,
|
||||||
Action::Render => self.render(tui)?,
|
Action::Render => self.render(tui)?,
|
||||||
Action::SetMode(_) => {
|
Action::SetMode(mode) => {
|
||||||
|
self.mode = mode;
|
||||||
self.action_tx
|
self.action_tx
|
||||||
.send(Action::UpdateFooter(String::from("(Enter) to select")))?;
|
.send(Action::UpdateFooter(String::from("(Enter) to select")))?;
|
||||||
let (title, labels, items, select_one) = build_left_items(self);
|
let (title, labels, items, select_one) = build_left_items(self);
|
||||||
|
|
@ -254,6 +255,11 @@ impl App {
|
||||||
self.action_tx
|
self.action_tx
|
||||||
.send(Action::UpdateRight(labels, start, items))?;
|
.send(Action::UpdateRight(labels, start, items))?;
|
||||||
}
|
}
|
||||||
|
Action::UpdateFooter(_)
|
||||||
|
| Action::UpdateLeft(_, _, _, _)
|
||||||
|
| Action::UpdateRight(_, _, _) => {
|
||||||
|
info!("Processing Action: {:?}", action);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
for component in &mut self.components {
|
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) {
|
fn build_left_items(app: &App) -> (String, Vec<String>, Vec<String>, bool) {
|
||||||
let title = String::from("Tools");
|
let title = String::from("Tools");
|
||||||
|
let labels = vec![String::new(), String::new()];
|
||||||
let items = app
|
let items = app
|
||||||
.menu
|
.menu
|
||||||
.tools
|
.tools
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tool| tool.name.clone())
|
.map(|tool| tool.name.clone())
|
||||||
.collect();
|
.collect();
|
||||||
let labels: Vec<String> = Vec::new();
|
(title, labels, items, false)
|
||||||
(title, labels, items, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_right_items(app: &App) -> (Vec<Vec<DVLine>>, usize, Vec<Vec<DVLine>>) {
|
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
|
.menu
|
||||||
.tools
|
.tools
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| DVLine {
|
.map(|entry| {
|
||||||
line_parts: vec![item.description.clone()],
|
vec![
|
||||||
line_colors: vec![Color::Reset],
|
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()];
|
.collect();
|
||||||
let labels: Vec<Vec<DVLine>> = Vec::new();
|
|
||||||
let start_index = 0;
|
let start_index = 0;
|
||||||
(labels, start_index, items)
|
(labels, start_index, items)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue