Use separate State structs per app

This commit is contained in:
2Shirt 2025-11-08 16:17:34 -08:00
parent ee7de8f355
commit 7e12223344
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
8 changed files with 166 additions and 104 deletions

View file

@ -26,7 +26,7 @@ use core::{
}, },
config::Config, config::Config,
line::{DVLine, get_disk_description_right, get_part_description}, line::{DVLine, get_disk_description_right, get_part_description},
state::{CloneSettings, Mode}, state::Mode,
system::{ system::{
boot::{self, SafeMode, configure_disk}, boot::{self, SafeMode, configure_disk},
cpu::get_cpu_name, cpu::get_cpu_name,
@ -57,6 +57,7 @@ use crate::{
parse_dism, parse_registry_hives, parse_system_files, parse_dism, parse_registry_hives, parse_system_files,
}, },
scan, scan,
state::State,
}; };
pub struct App { pub struct App {
@ -71,13 +72,13 @@ pub struct App {
should_suspend: bool, should_suspend: bool,
tick_rate: f64, tick_rate: f64,
// App // App
clone: CloneSettings,
cur_mode: Mode, cur_mode: Mode,
diag_groups: Arc<Mutex<Vec<DiagGroup>>>, diag_groups: Arc<Mutex<Vec<DiagGroup>>>,
list: StatefulList<Mode>, list: StatefulList<Mode>,
boot_modes: Vec<SafeMode>, boot_modes: Vec<SafeMode>,
setup_modes: Vec<SafeMode>, setup_modes: Vec<SafeMode>,
selections: Vec<Option<usize>>, selections: Vec<Option<usize>>,
state: State,
system32: String, system32: String,
tasks: Tasks, tasks: Tasks,
} }
@ -117,7 +118,7 @@ impl App {
should_suspend: false, should_suspend: false,
tick_rate, tick_rate,
// App // App
clone: CloneSettings::new(disk_list_arc), state: State::new(disk_list_arc),
cur_mode: Mode::Home, cur_mode: Mode::Home,
diag_groups: diag_groups_arc, diag_groups: diag_groups_arc,
list, list,
@ -130,12 +131,12 @@ impl App {
} }
pub fn inject_driver(&mut self, index: usize) { pub fn inject_driver(&mut self, index: usize) {
if let Some(driver) = self.clone.driver_list.get(index) if let Some(driver) = self.state.driver_list.get(index)
&& let Some(disk_index) = self.clone.disk_index_dest && let Some(disk_index) = self.state.disk_index_dest
{ {
let disk_list = self.clone.disk_list.lock().unwrap(); let disk_list = self.state.disk_list.lock().unwrap();
if let Some(disk) = disk_list.get(disk_index) if let Some(disk) = disk_list.get(disk_index)
&& let Some(os_index) = self.clone.part_index_os && let Some(os_index) = self.state.part_index_os
&& let Ok(task) = boot::inject_driver( && let Ok(task) = boot::inject_driver(
driver, driver,
disk.get_part_letter(os_index).as_str(), disk.get_part_letter(os_index).as_str(),
@ -171,10 +172,10 @@ impl App {
SafeMode::Enable => "Safe Mode (minimal)", SafeMode::Enable => "Safe Mode (minimal)",
}; };
info!("Setting boot mode to: {new_mode}"); info!("Setting boot mode to: {new_mode}");
let disk_list = self.clone.disk_list.lock().unwrap(); let disk_list = self.state.disk_list.lock().unwrap();
if let Some(disk_index) = self.clone.disk_index_dest if let Some(disk_index) = self.state.disk_index_dest
&& let Some(disk) = disk_list.get(disk_index) && let Some(disk) = disk_list.get(disk_index)
&& let Some(boot_index) = self.clone.part_index_boot && let Some(boot_index) = self.state.part_index_boot
&& let Ok(task) = boot::set_mode( && let Ok(task) = boot::set_mode(
disk.get_part_letter(boot_index).as_str(), disk.get_part_letter(boot_index).as_str(),
&boot_mode, &boot_mode,
@ -202,13 +203,13 @@ impl App {
))?; ))?;
scan::queue_boot_scan_tasks( scan::queue_boot_scan_tasks(
self.action_tx.clone(), self.action_tx.clone(),
&self.clone,
self.diag_groups.clone(), self.diag_groups.clone(),
&self.state,
self.system32.clone(), self.system32.clone(),
&mut self.tasks, &mut self.tasks,
)?; )?;
} }
Mode::InjectDrivers | Mode::InstallDrivers => self.clone.scan_drivers(), Mode::InjectDrivers | Mode::InstallDrivers => self.state.scan_drivers(),
Mode::Process => { Mode::Process => {
self.action_tx self.action_tx
.send(Action::DisplayPopup(popup::Type::Info, String::from("...")))?; .send(Action::DisplayPopup(popup::Type::Info, String::from("...")))?;
@ -383,10 +384,10 @@ impl App {
} }
Mode::InstallDrivers => { Mode::InstallDrivers => {
if let Some(index) = one if let Some(index) = one
&& let Some(driver) = self.clone.driver_list.get(index).cloned() && let Some(driver) = self.state.driver_list.get(index).cloned()
{ {
drivers::load(&driver.inf_paths); drivers::load(&driver.inf_paths);
self.clone.driver = Some(driver); self.state.driver = Some(driver);
} }
} }
Mode::BootSetup => { Mode::BootSetup => {
@ -398,11 +399,11 @@ impl App {
} }
} }
Mode::SelectDisks => { Mode::SelectDisks => {
self.clone.disk_index_dest = one; self.state.disk_index_dest = one;
} }
Mode::SelectParts => { Mode::SelectParts => {
self.clone.part_index_boot = one; self.state.part_index_boot = one;
self.clone.part_index_os = two; self.state.part_index_os = two;
} }
Mode::SetBootMode => { Mode::SetBootMode => {
if let Some(index) = one if let Some(index) = one
@ -683,7 +684,7 @@ fn build_left_items(app: &App) -> Action {
Mode::InstallDrivers => { Mode::InstallDrivers => {
select_type = SelectionType::One; select_type = SelectionType::One;
title = String::from("Install Drivers"); title = String::from("Install Drivers");
app.clone app.state
.driver_list .driver_list
.iter() .iter()
.for_each(|driver| items.push(driver.to_string())); .for_each(|driver| items.push(driver.to_string()));
@ -691,7 +692,7 @@ fn build_left_items(app: &App) -> Action {
Mode::InjectDrivers => { Mode::InjectDrivers => {
select_type = SelectionType::One; select_type = SelectionType::One;
title = String::from("Select Drivers"); title = String::from("Select Drivers");
app.clone app.state
.driver_list .driver_list
.iter() .iter()
.for_each(|driver| items.push(driver.to_string())); .for_each(|driver| items.push(driver.to_string()));
@ -699,7 +700,7 @@ fn build_left_items(app: &App) -> Action {
Mode::SelectDisks => { Mode::SelectDisks => {
select_type = SelectionType::One; select_type = SelectionType::One;
title = String::from("Select Disk"); title = String::from("Select Disk");
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
disk_list disk_list
.iter() .iter()
.for_each(|disk| items.push(disk.description.to_string())); .for_each(|disk| items.push(disk.description.to_string()));
@ -713,8 +714,8 @@ fn build_left_items(app: &App) -> Action {
title = String::from("Select Boot and OS Partitions"); title = String::from("Select Boot and OS Partitions");
labels[0] = String::from("boot"); labels[0] = String::from("boot");
labels[1] = String::from("os"); labels[1] = String::from("os");
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(index) = app.clone.disk_index_dest if let Some(index) = app.state.disk_index_dest
&& let Some(disk) = disk_list.get(index) && let Some(disk) = disk_list.get(index)
{ {
disk.get_parts().iter().for_each(|part| { disk.get_parts().iter().for_each(|part| {
@ -854,7 +855,7 @@ fn build_right_items(app: &App) -> Action {
line_colors: vec![Color::Cyan], line_colors: vec![Color::Cyan],
}; };
labels.push(vec![dest_dv_line]); labels.push(vec![dest_dv_line]);
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
disk_list disk_list
.iter() .iter()
.for_each(|disk| items.push(get_disk_description_right(disk, &None))); .for_each(|disk| items.push(get_disk_description_right(disk, &None)));
@ -866,9 +867,9 @@ fn build_right_items(app: &App) -> Action {
line_colors: vec![Color::Cyan], line_colors: vec![Color::Cyan],
}]) }])
}); });
if let Some(index) = app.clone.disk_index_dest { if let Some(index) = app.state.disk_index_dest {
start_index += 1; start_index += 1;
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(disk) = disk_list.get(index) { if let Some(disk) = disk_list.get(index) {
// Disk Details // Disk Details
items.push(get_disk_description_right(disk, &None)); items.push(get_disk_description_right(disk, &None));
@ -897,11 +898,11 @@ fn build_right_items(app: &App) -> Action {
fn create_boot_files(app: &mut App, safe_mode: SafeMode) { fn create_boot_files(app: &mut App, safe_mode: SafeMode) {
let mut tasks: Vec<TaskType> = Vec::new(); let mut tasks: Vec<TaskType> = Vec::new();
if let Some(index) = app.clone.disk_index_dest { if let Some(index) = app.state.disk_index_dest {
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(disk) = disk_list.get(index) { if let Some(disk) = disk_list.get(index) {
let letter_boot = disk.get_part_letter(app.clone.part_index_boot.unwrap()); let letter_boot = disk.get_part_letter(app.state.part_index_boot.unwrap());
let letter_os = disk.get_part_letter(app.clone.part_index_os.unwrap()); let letter_os = disk.get_part_letter(app.state.part_index_os.unwrap());
tasks = configure_disk( tasks = configure_disk(
&letter_boot, &letter_boot,
&letter_os, &letter_os,
@ -918,14 +919,14 @@ fn create_boot_files(app: &mut App, safe_mode: SafeMode) {
fn get_disk_header(app: &App) -> Vec<DVLine> { fn get_disk_header(app: &App) -> Vec<DVLine> {
let mut header_lines: Vec<DVLine> = Vec::new(); let mut header_lines: Vec<DVLine> = Vec::new();
if let Some(index) = app.clone.disk_index_dest { if let Some(index) = app.state.disk_index_dest {
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(disk) = disk_list.get(index) { if let Some(disk) = disk_list.get(index) {
let mut parts: Vec<usize> = Vec::new(); let mut parts: Vec<usize> = Vec::new();
if let Some(index) = app.clone.part_index_boot { if let Some(index) = app.state.part_index_boot {
parts.push(index); parts.push(index);
} }
if let Some(index) = app.clone.part_index_os { if let Some(index) = app.state.part_index_os {
parts.push(index); parts.push(index);
} }
header_lines.append(&mut get_disk_description_right(disk, &Some(parts))); header_lines.append(&mut get_disk_description_right(disk, &Some(parts)));

View file

@ -22,6 +22,7 @@ mod app;
mod components; mod components;
mod diags; mod diags;
mod scan; mod scan;
mod state;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {

View file

@ -1,5 +1,4 @@
use color_eyre::Result; use color_eyre::Result;
use core::state::CloneSettings;
use core::system::disk::PartitionTableType; use core::system::disk::PartitionTableType;
use core::tasks::Tasks; use core::tasks::Tasks;
use core::{action::Action, tasks::TaskType}; use core::{action::Action, tasks::TaskType};
@ -8,24 +7,25 @@ use std::sync::{Arc, Mutex};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::diags::{DiagGroup, Type as DiagType}; use crate::diags::{DiagGroup, Type as DiagType};
use crate::state::State;
pub fn queue_boot_scan_tasks( pub fn queue_boot_scan_tasks(
action_tx: mpsc::UnboundedSender<Action>, action_tx: mpsc::UnboundedSender<Action>,
clone: &CloneSettings,
diag_groups: Arc<Mutex<Vec<DiagGroup>>>, diag_groups: Arc<Mutex<Vec<DiagGroup>>>,
state: &State,
system32: String, system32: String,
tasks: &mut Tasks, tasks: &mut Tasks,
) -> Result<()> { ) -> Result<()> {
if let Ok(mut diag_groups) = diag_groups.lock() { if let Ok(mut diag_groups) = diag_groups.lock() {
diag_groups.clear(); diag_groups.clear();
} }
let disk_list = clone.disk_list.lock().unwrap(); let disk_list = state.disk_list.lock().unwrap();
if let Some(disk_index) = clone.disk_index_dest if let Some(disk_index) = state.disk_index_dest
&& let Some(disk) = disk_list.get(disk_index) && let Some(disk) = disk_list.get(disk_index)
{ {
let table_type = disk.part_type.clone(); let table_type = disk.part_type.clone();
let letter_boot = disk.get_part_letter(clone.part_index_boot.unwrap()); let letter_boot = disk.get_part_letter(state.part_index_boot.unwrap());
let letter_os = disk.get_part_letter(clone.part_index_os.unwrap()); let letter_os = disk.get_part_letter(state.part_index_os.unwrap());
// Safety check // Safety check
if letter_os.is_empty() { if letter_os.is_empty() {

42
boot_diags/src/state.rs Normal file
View file

@ -0,0 +1,42 @@
// 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 std::sync::{Arc, Mutex};
use core::system::{disk::Disk, drivers};
#[derive(Debug, Default)]
pub struct State {
pub disk_index_dest: Option<usize>,
pub disk_list: Arc<Mutex<Vec<Disk>>>,
pub driver_list: Vec<drivers::Driver>,
pub part_index_boot: Option<usize>,
pub part_index_os: Option<usize>,
pub driver: Option<drivers::Driver>,
}
impl State {
pub fn new(disk_list: Arc<Mutex<Vec<Disk>>>) -> Self {
State {
disk_list,
..Default::default()
}
}
pub fn scan_drivers(&mut self) {
self.driver_list = drivers::scan();
}
}

View file

@ -14,15 +14,8 @@
// 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 std::sync::{Arc, Mutex};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::system::{
disk::{Disk, PartitionTableType},
drivers,
};
#[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 {
// Core // Core
@ -52,28 +45,3 @@ pub enum Mode {
// WinPE // WinPE
PEMenu, PEMenu,
} }
#[derive(Debug, Default)]
pub struct CloneSettings {
pub disk_index_dest: Option<usize>,
pub disk_index_source: Option<usize>,
pub disk_list: Arc<Mutex<Vec<Disk>>>,
pub driver_list: Vec<drivers::Driver>,
pub part_index_boot: Option<usize>,
pub part_index_os: Option<usize>,
pub driver: Option<drivers::Driver>,
pub table_type: Option<PartitionTableType>,
}
impl CloneSettings {
pub fn new(disk_list: Arc<Mutex<Vec<Disk>>>) -> Self {
CloneSettings {
disk_list,
..Default::default()
}
}
pub fn scan_drivers(&mut self) {
self.driver_list = drivers::scan();
}
}

View file

@ -26,7 +26,7 @@ use core::{
}, },
config::Config, config::Config,
line::{DVLine, get_disk_description_right, get_part_description}, line::{DVLine, get_disk_description_right, get_part_description},
state::{CloneSettings, Mode}, state::Mode,
system::{ system::{
boot, cpu::get_cpu_name, disk::PartitionTableType, diskpart::build_dest_format_script, boot, cpu::get_cpu_name, disk::PartitionTableType, diskpart::build_dest_format_script,
drivers, drivers,
@ -51,6 +51,8 @@ use ratatui::{
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tracing::{debug, info}; use tracing::{debug, info};
use crate::state::State;
pub struct App { pub struct App {
// TUI // TUI
action_rx: mpsc::UnboundedReceiver<Action>, action_rx: mpsc::UnboundedReceiver<Action>,
@ -63,11 +65,11 @@ pub struct App {
should_suspend: bool, should_suspend: bool,
tick_rate: f64, tick_rate: f64,
// App // App
clone: CloneSettings,
cur_mode: Mode, cur_mode: Mode,
list: StatefulList<usize>, list: StatefulList<usize>,
prev_mode: Mode, prev_mode: Mode,
selections: Vec<Option<usize>>, selections: Vec<Option<usize>>,
state: State,
tasks: Tasks, tasks: Tasks,
} }
@ -94,7 +96,7 @@ impl App {
should_suspend: false, should_suspend: false,
tick_rate, tick_rate,
// App // App
clone: CloneSettings::new(disk_list_arc), state: State::new(disk_list_arc),
cur_mode: Mode::default(), cur_mode: Mode::default(),
list: StatefulList::default(), list: StatefulList::default(),
prev_mode: Mode::default(), prev_mode: Mode::default(),
@ -167,7 +169,7 @@ impl App {
info!("Setting mode to {new_mode:?}"); info!("Setting mode to {new_mode:?}");
self.cur_mode = new_mode; self.cur_mode = new_mode;
match new_mode { match new_mode {
Mode::InstallDrivers => self.clone.scan_drivers(), Mode::InstallDrivers => self.state.scan_drivers(),
Mode::ScanDisks => { Mode::ScanDisks => {
self.prev_mode = self.cur_mode; self.prev_mode = self.cur_mode;
if self.tasks.idle() { if self.tasks.idle() {
@ -194,11 +196,11 @@ impl App {
)); ));
// Build Diskpart script to format destination disk // Build Diskpart script to format destination disk
let disk_list = self.clone.disk_list.lock().unwrap(); let disk_list = self.state.disk_list.lock().unwrap();
if let Some(disk_index) = self.clone.disk_index_dest if let Some(disk_index) = self.state.disk_index_dest
&& let Some(disk) = disk_list.get(disk_index) && let Some(disk) = disk_list.get(disk_index)
{ {
let table_type = self.clone.table_type.clone().unwrap(); let table_type = self.state.table_type.clone().unwrap();
let diskpart_script = build_dest_format_script(disk.id, &table_type); let diskpart_script = build_dest_format_script(disk.id, &table_type);
self.tasks.add(TaskType::Diskpart(diskpart_script)); self.tasks.add(TaskType::Diskpart(diskpart_script));
} }
@ -212,7 +214,7 @@ impl App {
self.config.clone_app_path.clone(), self.config.clone_app_path.clone(),
Vec::new(), Vec::new(),
)); ));
if let Some(dest_index) = self.clone.disk_index_dest { if let Some(dest_index) = self.state.disk_index_dest {
self.tasks.add(TaskType::UpdateDestDisk(dest_index)); self.tasks.add(TaskType::UpdateDestDisk(dest_index));
} }
} }
@ -226,13 +228,13 @@ impl App {
let system32 = get_system32_path(&self.action_tx); let system32 = get_system32_path(&self.action_tx);
// Add actions // Add actions
let disk_list = self.clone.disk_list.lock().unwrap(); let disk_list = self.state.disk_list.lock().unwrap();
if let Some(disk_index) = self.clone.disk_index_dest if let Some(disk_index) = self.state.disk_index_dest
&& let Some(disk) = disk_list.get(disk_index) && let Some(disk) = disk_list.get(disk_index)
{ {
let table_type = self.clone.table_type.clone().unwrap(); let table_type = self.state.table_type.clone().unwrap();
let letter_boot = disk.get_part_letter(self.clone.part_index_boot.unwrap()); let letter_boot = disk.get_part_letter(self.state.part_index_boot.unwrap());
let letter_os = disk.get_part_letter(self.clone.part_index_os.unwrap()); let letter_os = disk.get_part_letter(self.state.part_index_os.unwrap());
// Safety check // Safety check
if letter_boot.is_empty() || letter_os.is_empty() { if letter_boot.is_empty() || letter_os.is_empty() {
@ -254,7 +256,7 @@ impl App {
} }
// Inject driver(s) (if selected) // Inject driver(s) (if selected)
if let Some(driver) = &self.clone.driver { if let Some(driver) = &self.state.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 {
@ -414,22 +416,22 @@ impl App {
match self.cur_mode { match self.cur_mode {
Mode::InstallDrivers => { Mode::InstallDrivers => {
if let Some(index) = one if let Some(index) = one
&& let Some(driver) = self.clone.driver_list.get(index).cloned() && let Some(driver) = self.state.driver_list.get(index).cloned()
{ {
drivers::load(&driver.inf_paths); drivers::load(&driver.inf_paths);
self.clone.driver = Some(driver); self.state.driver = Some(driver);
} }
} }
Mode::SelectDisks => { Mode::SelectDisks => {
self.clone.disk_index_source = one; self.state.disk_index_source = one;
self.clone.disk_index_dest = two; self.state.disk_index_dest = two;
} }
Mode::SelectParts => { Mode::SelectParts => {
self.clone.part_index_boot = one; self.state.part_index_boot = one;
self.clone.part_index_os = two; self.state.part_index_os = two;
} }
Mode::SelectTableType => { Mode::SelectTableType => {
self.clone.table_type = { self.state.table_type = {
if let Some(index) = one { if let Some(index) = one {
match index { match index {
0 => Some(PartitionTableType::Guid), 0 => Some(PartitionTableType::Guid),
@ -452,7 +454,7 @@ impl App {
// Clear TableType selection // Clear TableType selection
match new_mode { match new_mode {
Mode::SelectDisks | Mode::SelectTableType => { Mode::SelectDisks | Mode::SelectTableType => {
self.clone.table_type = None; self.state.table_type = None;
} }
_ => {} _ => {}
} }
@ -466,8 +468,8 @@ impl App {
Mode::SelectTableType | Mode::Confirm => { Mode::SelectTableType | Mode::Confirm => {
// Select source/dest disks // Select source/dest disks
self.action_tx.send(Action::SelectRight( self.action_tx.send(Action::SelectRight(
self.clone.disk_index_source, self.state.disk_index_source,
self.clone.disk_index_dest, self.state.disk_index_dest,
))?; ))?;
} }
Mode::SelectParts => { Mode::SelectParts => {
@ -475,7 +477,7 @@ impl App {
self.action_tx.send(Action::Select(Some(0), None))?; self.action_tx.send(Action::Select(Some(0), None))?;
// Highlight 2nd or 3rd partition as OS partition // Highlight 2nd or 3rd partition as OS partition
let index = if let Some(table_type) = &self.clone.table_type { let index = if let Some(table_type) = &self.state.table_type {
match table_type { match table_type {
PartitionTableType::Guid => 2, PartitionTableType::Guid => 2,
PartitionTableType::Legacy => 1, PartitionTableType::Legacy => 1,
@ -649,7 +651,7 @@ fn build_left_items(app: &App, cur_mode: Mode) -> Action {
Mode::InstallDrivers => { Mode::InstallDrivers => {
select_type = SelectionType::One; select_type = SelectionType::One;
title = String::from("Install Drivers"); title = String::from("Install Drivers");
app.clone app.state
.driver_list .driver_list
.iter() .iter()
.for_each(|driver| items.push(driver.to_string())); .for_each(|driver| items.push(driver.to_string()));
@ -659,7 +661,7 @@ fn build_left_items(app: &App, cur_mode: Mode) -> Action {
title = String::from("Select Source and Destination Disks"); title = String::from("Select Source and Destination Disks");
labels.push(String::from("source")); labels.push(String::from("source"));
labels.push(String::from("dest")); labels.push(String::from("dest"));
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
disk_list disk_list
.iter() .iter()
.for_each(|disk| items.push(disk.description.to_string())); .for_each(|disk| items.push(disk.description.to_string()));
@ -683,8 +685,8 @@ fn build_left_items(app: &App, cur_mode: Mode) -> Action {
title = String::from("Select Boot and OS Partitions"); title = String::from("Select Boot and OS Partitions");
labels.push(String::from("boot")); labels.push(String::from("boot"));
labels.push(String::from("os")); labels.push(String::from("os"));
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(index) = app.clone.disk_index_dest if let Some(index) = app.state.disk_index_dest
&& let Some(disk) = disk_list.get(index) && let Some(disk) = disk_list.get(index)
{ {
disk.get_parts().iter().for_each(|part| { disk.get_parts().iter().for_each(|part| {
@ -739,7 +741,7 @@ fn build_right_items(app: &App, cur_mode: Mode) -> Action {
], ],
line_colors: vec![Color::Cyan, Color::Red], line_colors: vec![Color::Cyan, Color::Red],
}; };
if let Some(table_type) = &app.clone.table_type { if let Some(table_type) = &app.state.table_type {
// Show table type // Show table type
let type_str = match table_type { let type_str = match table_type {
PartitionTableType::Guid => "GPT", PartitionTableType::Guid => "GPT",
@ -755,7 +757,7 @@ fn build_right_items(app: &App, cur_mode: Mode) -> Action {
} else { } else {
labels.push(vec![dest_dv_line]); labels.push(vec![dest_dv_line]);
} }
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
disk_list disk_list
.iter() .iter()
.for_each(|disk| items.push(get_disk_description_right(disk, &None))); .for_each(|disk| items.push(get_disk_description_right(disk, &None)));
@ -767,9 +769,9 @@ fn build_right_items(app: &App, cur_mode: Mode) -> Action {
line_colors: vec![Color::Cyan], line_colors: vec![Color::Cyan],
}]); }]);
} }
if let Some(index) = app.clone.disk_index_dest { if let Some(index) = app.state.disk_index_dest {
start_index = 1; start_index = 1;
let disk_list = app.clone.disk_list.lock().unwrap(); let disk_list = app.state.disk_list.lock().unwrap();
if let Some(disk) = disk_list.get(index) { if let Some(disk) = disk_list.get(index) {
// Disk Details // Disk Details
items.push(get_disk_description_right(disk, &None)); items.push(get_disk_description_right(disk, &None));

View file

@ -19,6 +19,7 @@ use color_eyre::Result;
use crate::app::App; use crate::app::App;
mod app; mod app;
mod state;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {

47
deja_vu/src/state.rs Normal file
View file

@ -0,0 +1,47 @@
// 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 std::sync::{Arc, Mutex};
use core::system::{
disk::{Disk, PartitionTableType},
drivers,
};
#[derive(Debug, Default)]
pub struct State {
pub disk_index_dest: Option<usize>,
pub disk_index_source: Option<usize>,
pub disk_list: Arc<Mutex<Vec<Disk>>>,
pub driver_list: Vec<drivers::Driver>,
pub part_index_boot: Option<usize>,
pub part_index_os: Option<usize>,
pub driver: Option<drivers::Driver>,
pub table_type: Option<PartitionTableType>,
}
impl State {
pub fn new(disk_list: Arc<Mutex<Vec<Disk>>>) -> Self {
State {
disk_list,
..Default::default()
}
}
pub fn scan_drivers(&mut self) {
self.driver_list = drivers::scan();
}
}