diff --git a/src/action.rs b/src/action.rs index 98824fc..bf8ce58 100644 --- a/src/action.rs +++ b/src/action.rs @@ -14,6 +14,7 @@ // along with Deja-vu. If not, see . // use serde::{Deserialize, Serialize}; +use std::path::PathBuf; use strum::Display; use crate::{ @@ -28,14 +29,15 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq, Display, Serialize, Deserialize)] pub enum Action { // App - Command(String, String, Vec), // (label, command, args) - Diskpart(String, String), // (label, script_as_string) + Command(String, PathBuf, Vec), // (label, command, args) + Diskpart(String, String), // (label, script_as_string) InstallDriver, Process, ScanDisks, Select(Option, Option), // indicies for (source, dest) or (boot, os) SelectDriver(Driver), SelectTableType(PartitionTableType), + UpdateDestDisk, UpdateDiskList(Vec), // Screens DismissPopup, diff --git a/src/app.rs b/src/app.rs index 9b53cb0..7cd42d9 100644 --- a/src/app.rs +++ b/src/app.rs @@ -15,8 +15,10 @@ // use std::{ iter::zip, + path::PathBuf, sync::{Arc, Mutex}, - thread::{self, JoinHandle}, + thread::{self, sleep, JoinHandle}, + time::Duration, }; use color_eyre::Result; @@ -32,17 +34,12 @@ use tracing::{debug, info}; use crate::{ action::Action, components::{ - footer::Footer, - fps::FpsCounter, - left::Left, - popup::{Popup, Type}, - right::Right, - title::Title, - Component, + footer::Footer, fps::FpsCounter, left::Left, popup, right::Right, title::Title, Component, }, config::Config, system::{ disk::{get_disks, Disk, PartitionTableType}, + diskpart::refresh_disk_info, drivers::{self, Driver}, }, tui::{Event, Tui}, @@ -101,7 +98,7 @@ impl App { Box::new(Left::new()), Box::new(Right::new()), Box::new(Footer::new()), - Box::new(Popup::new()), + Box::new(popup::Popup::new()), ], config: Config::new()?, frame_rate, @@ -278,6 +275,21 @@ impl App { Action::Suspend => self.should_suspend = true, Action::Resume => self.should_suspend = false, Action::ClearScreen => tui.terminal.clear()?, + Action::Command(ref label, ref cmd_path, ref cmd_args) => { + self.action_tx.send(Action::DisplayPopup( + popup::Type::Info, + String::from(&label.to_owned()), + ))?; + self.task_handles + .push(lazy_command(&cmd_path, cmd_args.clone())) + } + Action::Diskpart(ref label, ref script) => { + self.action_tx.send(Action::DisplayPopup( + popup::Type::Info, + String::from(&label.to_owned()), + ))?; + self.task_handles.push(lazy_diskpart(&script.to_owned())) + } Action::InstallDriver => { self.action_tx.send(Action::SetMode(Mode::InstallDrivers))? } @@ -297,6 +309,7 @@ impl App { } Action::NextScreen => { if let Some(mode) = self.next_mode() { + self.action_tx.send(Action::DismissPopup)?; self.action_tx.send(Action::SetMode(mode))?; } } @@ -331,15 +344,48 @@ impl App { self.action_tx .send(Action::UpdateDiskList(disk_list.clone()))?; } + Mode::PreClone => { + // TODO: FIXME + self.action_tx.send(Action::Diskpart( + String::from("Formatting destination disk"), + String::from("TODO: FIXME"), + ))?; + } + Mode::Clone => { + self.action_tx.send(Action::UpdateDestDisk)?; + self.action_tx.send(Action::Command( + String::from("Running Clone Tool"), + self.config.clone_app_path.clone(), + Vec::new(), + ))?; + } + Mode::PostClone => { + // TODO: FIXME + self.action_tx.send(Action::Diskpart( + String::from("Creating boot files"), + String::from("TODO: FIXME"), + ))?; + } Mode::Done => { self.action_tx.send(Action::DisplayPopup( - Type::Success, + popup::Type::Success, String::from("COMPLETE\n\n\nThank you for using this tool!"), ))?; } _ => {} } } + Action::UpdateDestDisk => { + let disk_list_arc = Arc::clone(&self.disk_list); + if let Some(dest_id_index) = self.disk_id_dest { + self.action_tx.send(Action::DisplayPopup( + popup::Type::Info, + String::from("Updating info for destination disk"), + ))?; + self.task_handles + .push(lazy_update_dest_disk(disk_list_arc, dest_id_index)); + } + } _ => {} } for component in self.components.iter_mut() { @@ -432,9 +478,41 @@ fn get_chunks(r: Rect) -> Vec { chunks } +fn lazy_command(cmd_path: &PathBuf, cmd_args: Vec) -> JoinHandle<()> { + if cfg!(windows) { + // TODO: FIXME + thread::spawn(|| sleep(Duration::from_secs(1))) + } else { + thread::spawn(|| sleep(Duration::from_secs(1))) + } +} + +fn lazy_diskpart(script: &str) -> JoinHandle<()> { + if cfg!(windows) { + // TODO: FIXME + thread::spawn(|| sleep(Duration::from_secs(1))) + } else { + thread::spawn(|| sleep(Duration::from_secs(1))) + } +} + fn lazy_get_disks(disk_list_arc: Arc>>) -> JoinHandle<()> { thread::spawn(move || { let mut disks = disk_list_arc.lock().unwrap(); *disks = get_disks(); }) } + +fn lazy_update_dest_disk( + disk_list_arc: Arc>>, + dest_index: usize, +) -> JoinHandle<()> { + if cfg!(windows) { + thread::spawn(move || { + let mut disks = disk_list_arc.lock().unwrap(); + refresh_disk_info(&mut disks[dest_index]); + }) + } else { + thread::spawn(|| sleep(Duration::from_secs(2))) + } +} diff --git a/src/components/left.rs b/src/components/left.rs index c60c5f9..3d2c10e 100644 --- a/src/components/left.rs +++ b/src/components/left.rs @@ -202,9 +202,6 @@ impl Component for Left { self.selections[0] = None; self.selections[1] = None; self.title_text = String::from("Select Source and Destination Disks"); - if let Some(command_tx) = self.command_tx.clone() { - command_tx.send(Action::DismissPopup)?; - } } (_, Mode::SelectTableType) => { self.list_table_types diff --git a/src/config.rs b/src/config.rs index eb62250..4fb882c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,6 +40,8 @@ pub struct AppConfig { #[derive(Clone, Debug, Default, Deserialize)] pub struct Config { + #[serde(default)] + pub clone_app_path: PathBuf, #[serde(default, flatten)] pub config: AppConfig, #[serde(default)] @@ -67,7 +69,11 @@ impl Config { let config_dir = get_config_dir(); let mut builder = config::Config::builder() .set_default("data_dir", data_dir.to_str().unwrap())? - .set_default("config_dir", config_dir.to_str().unwrap())?; + .set_default("config_dir", config_dir.to_str().unwrap())? + .set_default( + "clone_app_path", + String::from("C:\\Program Files\\Some Clone Tool\\app.exe"), + )?; let config_files = [ ("config.json5", config::FileFormat::Json5),