Compare commits
No commits in common. "3674fbdee760894ffcca360652fac754614d7073" and "f6d01068a3bf3ef98a343375d18d808e1ced784a" have entirely different histories.
3674fbdee7
...
f6d01068a3
9 changed files with 21 additions and 138 deletions
|
|
@ -87,41 +87,5 @@
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
"<Ctrl-c>": "Quit", // Yet another way to quit
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
"<Ctrl-z>": "Suspend" // Suspend the application
|
||||||
},
|
},
|
||||||
// Diagnostic modes
|
|
||||||
"DiagMenu": {
|
|
||||||
"<Enter>": "Process",
|
|
||||||
"<q>": "Quit", // Quit the application
|
|
||||||
"<Ctrl-d>": "Quit", // Another way to quit
|
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
|
||||||
},
|
|
||||||
"BootDiags": {
|
|
||||||
"<Enter>": "Process",
|
|
||||||
"<q>": "Quit", // Quit the application
|
|
||||||
"<Ctrl-d>": "Quit", // Another way to quit
|
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
|
||||||
},
|
|
||||||
"BootSetup": {
|
|
||||||
"<Enter>": "Process",
|
|
||||||
"<q>": "Quit", // Quit the application
|
|
||||||
"<Ctrl-d>": "Quit", // Another way to quit
|
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
|
||||||
},
|
|
||||||
"InjectDrivers": {
|
|
||||||
"<Enter>": "Process",
|
|
||||||
"<q>": "Quit", // Quit the application
|
|
||||||
"<Ctrl-d>": "Quit", // Another way to quit
|
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
|
||||||
},
|
|
||||||
"ToggleSafeBoot": {
|
|
||||||
"<Enter>": "Process",
|
|
||||||
"<q>": "Quit", // Quit the application
|
|
||||||
"<Ctrl-d>": "Quit", // Another way to quit
|
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ use tracing::{debug, info};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::Action,
|
action::Action,
|
||||||
cli,
|
|
||||||
components::{
|
components::{
|
||||||
footer::Footer, fps::FpsCounter, left::Left, popup, right::Right, title::Title, Component,
|
footer::Footer, fps::FpsCounter, left::Left, popup, right::Right, title::Title, Component,
|
||||||
},
|
},
|
||||||
|
|
@ -58,7 +57,6 @@ pub struct App {
|
||||||
should_suspend: bool,
|
should_suspend: bool,
|
||||||
tick_rate: f64,
|
tick_rate: f64,
|
||||||
// App
|
// App
|
||||||
cli_cmd: cli::Command,
|
|
||||||
cur_mode: Mode,
|
cur_mode: Mode,
|
||||||
disk_index_dest: Option<usize>,
|
disk_index_dest: Option<usize>,
|
||||||
disk_index_source: Option<usize>,
|
disk_index_source: Option<usize>,
|
||||||
|
|
@ -86,16 +84,10 @@ pub enum Mode {
|
||||||
PostClone,
|
PostClone,
|
||||||
Done,
|
Done,
|
||||||
Failed,
|
Failed,
|
||||||
// Diagnostic modes
|
|
||||||
DiagMenu,
|
|
||||||
BootDiags,
|
|
||||||
BootSetup,
|
|
||||||
InjectDrivers,
|
|
||||||
ToggleSafeBoot,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(cli_cmd: cli::Command, 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 mut tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
|
||||||
|
|
@ -105,14 +97,13 @@ impl App {
|
||||||
action_rx,
|
action_rx,
|
||||||
action_tx,
|
action_tx,
|
||||||
components: vec![
|
components: vec![
|
||||||
Box::new(Title::new(cli_cmd)),
|
Box::new(Title::new()),
|
||||||
Box::new(FpsCounter::new()),
|
Box::new(FpsCounter::new()),
|
||||||
Box::new(Left::new()),
|
Box::new(Left::new()),
|
||||||
Box::new(Right::new()),
|
Box::new(Right::new()),
|
||||||
Box::new(Footer::new()),
|
Box::new(Footer::new()),
|
||||||
Box::new(popup::Popup::new()),
|
Box::new(popup::Popup::new()),
|
||||||
],
|
],
|
||||||
cli_cmd,
|
|
||||||
config: Config::new()?,
|
config: Config::new()?,
|
||||||
frame_rate,
|
frame_rate,
|
||||||
last_tick_key_events: Vec::new(),
|
last_tick_key_events: Vec::new(),
|
||||||
|
|
@ -120,10 +111,7 @@ impl App {
|
||||||
should_suspend: false,
|
should_suspend: false,
|
||||||
tick_rate,
|
tick_rate,
|
||||||
// App
|
// App
|
||||||
cur_mode: match cli_cmd {
|
cur_mode: Mode::ScanDisks,
|
||||||
cli::Command::Clone => Mode::ScanDisks,
|
|
||||||
cli::Command::Diagnose => Mode::DiagMenu,
|
|
||||||
},
|
|
||||||
disk_index_dest: None,
|
disk_index_dest: None,
|
||||||
disk_index_source: None,
|
disk_index_source: None,
|
||||||
disk_list: disk_list_arc,
|
disk_list: disk_list_arc,
|
||||||
|
|
@ -139,7 +127,6 @@ impl App {
|
||||||
|
|
||||||
pub fn next_mode(&mut self) -> Option<Mode> {
|
pub fn next_mode(&mut self) -> Option<Mode> {
|
||||||
let new_mode = match (self.prev_mode, self.cur_mode) {
|
let new_mode = match (self.prev_mode, self.cur_mode) {
|
||||||
// Clone states
|
|
||||||
(_, Mode::InstallDrivers) => Mode::ScanDisks,
|
(_, Mode::InstallDrivers) => Mode::ScanDisks,
|
||||||
(_, Mode::ScanDisks) => Mode::SelectDisks,
|
(_, Mode::ScanDisks) => Mode::SelectDisks,
|
||||||
(_, Mode::SelectDisks | Mode::SelectTableType | Mode::SelectParts) => {
|
(_, Mode::SelectDisks | Mode::SelectTableType | Mode::SelectParts) => {
|
||||||
|
|
@ -156,14 +143,6 @@ impl App {
|
||||||
(Mode::SelectParts, Mode::Confirm) => Mode::PostClone,
|
(Mode::SelectParts, Mode::Confirm) => Mode::PostClone,
|
||||||
(_, Mode::PostClone | Mode::Done) => Mode::Done,
|
(_, Mode::PostClone | Mode::Done) => Mode::Done,
|
||||||
(_, Mode::Failed) => Mode::Failed,
|
(_, Mode::Failed) => Mode::Failed,
|
||||||
|
|
||||||
// Diagnostic states
|
|
||||||
(_, Mode::DiagMenu) => Mode::BootDiags,
|
|
||||||
(_, Mode::BootDiags) => Mode::BootSetup,
|
|
||||||
(_, Mode::BootSetup) => Mode::InjectDrivers,
|
|
||||||
(_, Mode::InjectDrivers) => Mode::ToggleSafeBoot,
|
|
||||||
(_, Mode::ToggleSafeBoot) => Mode::Done,
|
|
||||||
|
|
||||||
// Invalid states
|
// Invalid states
|
||||||
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
||||||
};
|
};
|
||||||
|
|
@ -268,7 +247,7 @@ impl App {
|
||||||
|
|
||||||
// Inject driver(s) (if selected)
|
// Inject driver(s) (if selected)
|
||||||
if let Some(driver) = &self.driver {
|
if let Some(driver) = &self.driver {
|
||||||
if let Ok(task) = boot::inject_driver(driver, &letter_os, &system32) {
|
if let Ok(task) = boot::inject_driver(&driver, &letter_os, &system32) {
|
||||||
self.tasks.add(task);
|
self.tasks.add(task);
|
||||||
} else {
|
} else {
|
||||||
self.action_tx.send(Action::Error(format!(
|
self.action_tx.send(Action::Error(format!(
|
||||||
|
|
@ -309,16 +288,6 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
let action_tx = self.action_tx.clone();
|
let action_tx = self.action_tx.clone();
|
||||||
// Init based on cli::Command
|
|
||||||
match self.cli_cmd {
|
|
||||||
cli::Command::Clone => {
|
|
||||||
action_tx.send(Action::SetMode(Mode::ScanDisks))?;
|
|
||||||
}
|
|
||||||
cli::Command::Diagnose => {
|
|
||||||
action_tx.send(Action::SetMode(Mode::DiagMenu))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.handle_events(&mut tui).await?;
|
self.handle_events(&mut tui).await?;
|
||||||
self.handle_actions(&mut tui)?;
|
self.handle_actions(&mut tui)?;
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,13 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Deja-vu. If not, see <https://www.gnu.org/licenses/>.
|
// along with Deja-vu. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
use clap::{Parser, Subcommand};
|
use clap::Parser;
|
||||||
|
|
||||||
use crate::config::{get_config_dir, get_data_dir};
|
use crate::config::{get_config_dir, get_data_dir};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version = version(), about)]
|
#[command(author, version = version(), about)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
/// App mode
|
|
||||||
#[command(subcommand)]
|
|
||||||
pub cli_cmd: Command,
|
|
||||||
|
|
||||||
/// Tick rate, i.e. number of ticks per second
|
/// Tick rate, i.e. number of ticks per second
|
||||||
#[arg(short, long, value_name = "FLOAT", default_value_t = 4.0)]
|
#[arg(short, long, value_name = "FLOAT", default_value_t = 4.0)]
|
||||||
pub tick_rate: f64,
|
pub tick_rate: f64,
|
||||||
|
|
@ -33,15 +29,6 @@ pub struct Cli {
|
||||||
pub frame_rate: f64,
|
pub frame_rate: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Subcommand)]
|
|
||||||
pub enum Command {
|
|
||||||
/// Clone Windows from one disk to another
|
|
||||||
Clone,
|
|
||||||
|
|
||||||
/// Diagnose Windows boot issues
|
|
||||||
Diagnose,
|
|
||||||
}
|
|
||||||
|
|
||||||
const VERSION_MESSAGE: &str = concat!(
|
const VERSION_MESSAGE: &str = concat!(
|
||||||
env!("CARGO_PKG_VERSION"),
|
env!("CARGO_PKG_VERSION"),
|
||||||
"-",
|
"-",
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ impl Component for Footer {
|
||||||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||||
if let Action::SetMode(new_mode) = action {
|
if let Action::SetMode(new_mode) = action {
|
||||||
self.text = match new_mode {
|
self.text = match new_mode {
|
||||||
// Clone modes
|
|
||||||
Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
|
Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
|
||||||
String::from("(q) to quit")
|
String::from("(q) to quit")
|
||||||
}
|
}
|
||||||
|
|
@ -70,13 +69,6 @@ impl Component for Footer {
|
||||||
Mode::Done | Mode::Failed | Mode::InstallDrivers => {
|
Mode::Done | Mode::Failed | Mode::InstallDrivers => {
|
||||||
String::from("(Enter) or (q) to quit")
|
String::from("(Enter) or (q) to quit")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostic modes
|
|
||||||
Mode::DiagMenu
|
|
||||||
| Mode::BootDiags
|
|
||||||
| Mode::BootSetup
|
|
||||||
| Mode::InjectDrivers
|
|
||||||
| Mode::ToggleSafeBoot => String::from("(q) to quit"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -163,15 +163,6 @@ impl Component for Left {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mode::DiagMenu
|
|
||||||
| Mode::BootDiags
|
|
||||||
| Mode::BootSetup
|
|
||||||
| Mode::InjectDrivers
|
|
||||||
| Mode::ToggleSafeBoot => {
|
|
||||||
if let Some(command_tx) = self.command_tx.clone() {
|
|
||||||
command_tx.send(Action::NextScreen)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Action::Select(Some(index), None) => self.selections[0] = Some(index),
|
Action::Select(Some(index), None) => self.selections[0] = Some(index),
|
||||||
|
|
@ -227,13 +218,6 @@ impl Component for Left {
|
||||||
self.title_text = String::from("Confirm Selections (Again)");
|
self.title_text = String::from("Confirm Selections (Again)");
|
||||||
}
|
}
|
||||||
(_, Mode::Done | Mode::Failed) => self.title_text = String::from("Done"),
|
(_, Mode::Done | Mode::Failed) => self.title_text = String::from("Done"),
|
||||||
// Diagnostic states
|
|
||||||
(_, Mode::DiagMenu) => self.title_text = String::from("Main Menu"),
|
|
||||||
(_, Mode::BootDiags) => self.title_text = String::from("Boot Diagnostics"),
|
|
||||||
(_, Mode::BootSetup) => self.title_text = String::from("Boot Setup"),
|
|
||||||
(_, Mode::InjectDrivers) => self.title_text = String::from("Inject Drivers"),
|
|
||||||
(_, Mode::ToggleSafeBoot) => self.title_text = String::from("Toggle Safe Mode"),
|
|
||||||
|
|
||||||
// Invalid states
|
// Invalid states
|
||||||
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
||||||
}
|
}
|
||||||
|
|
@ -286,18 +270,10 @@ impl Component for Left {
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
match self.mode {
|
match self.mode {
|
||||||
// Clone modes
|
|
||||||
Mode::ScanDisks
|
Mode::ScanDisks
|
||||||
| Mode::PreClone
|
| Mode::PreClone
|
||||||
| Mode::Clone
|
| Mode::Clone
|
||||||
| Mode::PostClone
|
| Mode::PostClone
|
||||||
// Diagnostic modes
|
|
||||||
| Mode::DiagMenu
|
|
||||||
| Mode::BootDiags
|
|
||||||
| Mode::BootSetup
|
|
||||||
| Mode::InjectDrivers
|
|
||||||
| Mode::ToggleSafeBoot
|
|
||||||
// Done
|
|
||||||
| Mode::Done
|
| Mode::Done
|
||||||
| Mode::Failed => {
|
| Mode::Failed => {
|
||||||
// Leave blank
|
// Leave blank
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ pub struct Popup {
|
||||||
impl Popup {
|
impl Popup {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
popup_text: String::new(),
|
popup_text: String::from("Scanning Disks..."),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ impl Component for Right {
|
||||||
},
|
},
|
||||||
Action::Process => {
|
Action::Process => {
|
||||||
if self.prev_mode == Mode::SelectDisks && self.cur_mode == Mode::Confirm {
|
if self.prev_mode == Mode::SelectDisks && self.cur_mode == Mode::Confirm {
|
||||||
self.selected_disks.clone_from(&self.selections);
|
self.selected_disks = self.selections.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::Select(one, two) => {
|
Action::Select(one, two) => {
|
||||||
|
|
|
||||||
|
|
@ -21,25 +21,17 @@ use ratatui::{
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use super::Component;
|
use super::Component;
|
||||||
use crate::{action::Action, cli, config::Config};
|
use crate::{action::Action, config::Config};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Title {
|
pub struct Title {
|
||||||
command_tx: Option<UnboundedSender<Action>>,
|
command_tx: Option<UnboundedSender<Action>>,
|
||||||
config: Config,
|
config: Config,
|
||||||
title_text: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Title {
|
impl Title {
|
||||||
pub fn new(cli_cmd: cli::Command) -> Self {
|
pub fn new() -> Self {
|
||||||
let title_text = match cli_cmd {
|
Self::default()
|
||||||
cli::Command::Clone => String::from("Deja-Vu: Clone"),
|
|
||||||
cli::Command::Diagnose => String::from("Deja-Vu: Diagnostics"),
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
title_text,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,16 +46,19 @@ impl Component for Title {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||||
// match action {
|
match action {
|
||||||
// _ => {}
|
_ => {}
|
||||||
// }
|
}
|
||||||
// Ok(None)
|
Ok(None)
|
||||||
// }
|
}
|
||||||
|
|
||||||
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
|
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
|
||||||
// Title Block
|
// Title Block
|
||||||
let title_text = Span::styled(&self.title_text, Style::default().fg(Color::LightCyan));
|
let title_text = Span::styled(
|
||||||
|
"WizardKit: Clone Tool",
|
||||||
|
Style::default().fg(Color::LightCyan),
|
||||||
|
);
|
||||||
let title = Paragraph::new(Line::from(title_text).centered())
|
let title = Paragraph::new(Line::from(title_text).centered())
|
||||||
.block(Block::default().borders(Borders::ALL));
|
.block(Block::default().borders(Borders::ALL));
|
||||||
frame.render_widget(title, area);
|
frame.render_widget(title, area);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ async fn main() -> Result<()> {
|
||||||
crate::logging::init()?;
|
crate::logging::init()?;
|
||||||
|
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let mut app = App::new(args.cli_cmd, args.tick_rate, args.frame_rate)?;
|
let mut app = App::new(args.tick_rate, args.frame_rate)?;
|
||||||
app.run().await?;
|
app.run().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue