From c62c6c751c6bc0e735f24e0f16420b4684f75983 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sun, 3 Nov 2024 17:23:07 -0800 Subject: [PATCH] Run get_disks() in the background using a thread Allows app interaction while the scan is running --- .config/config.json5 | 1 - src/app.rs | 36 ++++++++++++++++++++++++++++++++---- src/components/footer.rs | 4 ++-- src/components/left.rs | 18 +++++++++--------- src/components/popup.rs | 22 ++-------------------- src/components/right.rs | 12 +++++++++--- src/system/disk.rs | 2 +- 7 files changed, 55 insertions(+), 40 deletions(-) diff --git a/.config/config.json5 b/.config/config.json5 index 7535430..f982a30 100644 --- a/.config/config.json5 +++ b/.config/config.json5 @@ -1,7 +1,6 @@ { "keybindings": { "ScanDisks": { - "": "Process", "": "Quit", // Quit the application "": "Quit", // Another way to quit "": "Quit", // Yet another way to quit diff --git a/src/app.rs b/src/app.rs index 3309712..5f2e2b6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -13,7 +13,11 @@ // You should have received a copy of the GNU General Public License // along with Deja-vu. If not, see . // -use std::iter::zip; +use std::{ + iter::zip, + sync::{Arc, Mutex}, + thread::{self, JoinHandle}, +}; use color_eyre::Result; use crossterm::event::KeyEvent; @@ -32,6 +36,7 @@ use crate::{ Component, }, config::Config, + system::disk::{get_disks, Disk}, tui::{Event, Tui}, }; @@ -40,6 +45,7 @@ pub struct App { tick_rate: f64, frame_rate: f64, components: Vec>, + disks: Arc>>, should_quit: bool, should_suspend: bool, cur_mode: Mode, @@ -74,6 +80,7 @@ impl App { Box::new(Footer::new()), Box::new(Popup::new()), ], + disks: Arc::new(Mutex::new(Vec::new())), should_quit: false, should_suspend: false, config: Config::new()?, @@ -114,6 +121,8 @@ impl App { } pub async fn run(&mut self) -> Result<()> { + let disk_wrapper = Arc::clone(&self.disks); + let _ = lazy_get_disks(disk_wrapper); let mut tui = Tui::new()? // .mouse(true) // uncomment this line to enable mouse support .tick_rate(self.tick_rate) @@ -203,6 +212,12 @@ impl App { match action { Action::Tick => { self.last_tick_key_events.drain(..); + // Continue to next screen if shared disks has been set + if self.cur_mode == Mode::ScanDisks { + if let Ok(_) = &self.disks.try_lock() { + self.action_tx.send(Action::NextScreen)?; + } + } } Action::Quit => self.should_quit = true, Action::Suspend => self.should_suspend = true, @@ -212,13 +227,17 @@ impl App { Action::Render => self.render(tui)?, Action::PrevScreen => { self.action_tx.send(Action::SetMode(self.prev_mode))?; - self.action_tx.send(Action::Select(None, None))?; } Action::NextScreen => { if let Some(mode) = self.next_mode() { self.action_tx.send(Action::SetMode(mode))?; } } + Action::ScanDisks => { + let disk_wrapper = Arc::clone(&self.disks); + let _ = lazy_get_disks(disk_wrapper); + self.action_tx.send(Action::SetMode(Mode::ScanDisks))?; + } Action::Select(one, two) => { self.selections[0] = one; self.selections[1] = two; @@ -228,8 +247,10 @@ impl App { match new_mode { Mode::ScanDisks => { self.prev_mode = self.cur_mode; - self.action_tx.send(Action::Select(None, None))?; - self.action_tx.send(Action::ScanDisks)?; + } + Mode::SelectDisks | Mode::SelectParts => { + let disks = self.disks.lock().unwrap(); + self.action_tx.send(Action::UpdateDiskList(disks.clone()))?; } Mode::Done => { self.action_tx.send(Action::DisplayPopup(String::from( @@ -330,3 +351,10 @@ fn get_chunks(r: Rect) -> Vec { // Done chunks } + +fn lazy_get_disks(disk_wrapper: Arc>>) -> JoinHandle<()> { + thread::spawn(move || { + let mut disks = disk_wrapper.lock().unwrap(); + *disks = get_disks(); + }) +} diff --git a/src/components/footer.rs b/src/components/footer.rs index 6b1b3d9..0a5d602 100644 --- a/src/components/footer.rs +++ b/src/components/footer.rs @@ -30,7 +30,7 @@ pub struct Footer { impl Footer { pub fn new() -> Self { Self { - footer_text: String::from("(Enter) to select / (b) to go back / (q) to quit"), + footer_text: String::from("(q) to quit"), ..Default::default() } } @@ -57,7 +57,7 @@ impl Component for Footer { } Action::SetMode(new_mode) => { self.footer_text = match new_mode { - Mode::ScanDisks => String::from("(Enter) to start / (q) to quit"), + Mode::ScanDisks => String::from("(q) to quit"), Mode::SelectDisks => String::from( "(Enter) to select / / (i) to install driver / (r) to rescan / (q) to quit", ), diff --git a/src/components/left.rs b/src/components/left.rs index e12403d..5e06eaf 100644 --- a/src/components/left.rs +++ b/src/components/left.rs @@ -69,11 +69,6 @@ impl Component for Left { Action::KeyUp => self.item_list.previous(), Action::KeyDown => self.item_list.next(), Action::Process => match self.mode { - Mode::ScanDisks => { - if let Some(command_tx) = self.command_tx.clone() { - command_tx.send(Action::ScanDisks)?; - } - } Mode::Confirm => { if let Some(command_tx) = self.command_tx.clone() { command_tx.send(Action::NextScreen)?; @@ -123,17 +118,22 @@ impl Component for Left { } _ => {} }, - Action::Select(None, None) => self.selections = vec![None, None], Action::Select(Some(index), None) => self.selections[0] = Some(index), Action::SetMode(new_mode) => { let prev_mode = self.mode; self.mode = new_mode; match new_mode { - Mode::ScanDisks => self.title_text = String::from(""), + Mode::ScanDisks => { + self.title_text = String::from(""); + self.item_list.clear_items(); + } Mode::SelectDisks => { self.selections[0] = None; self.selections[1] = None; - self.title_text = String::from("Select Source and Destination Disks") + 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::SelectParts => { self.selections[0] = None; @@ -171,7 +171,7 @@ impl Component for Left { // Body (scan disks) if self.item_list.items.is_empty() { - let paragraph = Paragraph::new(String::from("Press Enter to start!")).block( + let paragraph = Paragraph::new(String::new()).block( Block::default() .borders(Borders::ALL) .padding(Padding::new(1, 1, 1, 1)), diff --git a/src/components/popup.rs b/src/components/popup.rs index 9e073d5..8ca499a 100644 --- a/src/components/popup.rs +++ b/src/components/popup.rs @@ -1,4 +1,3 @@ -use clap::command; // This file is part of Deja-vu. // // Deja-vu is free software: you can redistribute it and/or modify it @@ -19,18 +18,12 @@ use ratatui::{prelude::*, widgets::*}; use tokio::sync::mpsc::UnboundedSender; use super::Component; -use crate::{ - action::Action, - app::Mode, - config::Config, - system::disk::{get_disks, Disk}, -}; +use crate::{action::Action, app::Mode, config::Config}; #[derive(Default)] pub struct Popup { command_tx: Option>, config: Config, - disks: Vec, popup_text: String, } @@ -64,18 +57,7 @@ impl Component for Popup { } Action::DismissPopup => self.popup_text.clear(), Action::DisplayPopup(new_text) => self.popup_text = String::from(new_text), - Action::ScanDisks => { - if let Some(command_tx) = self.command_tx.clone() { - self.disks = get_disks(); - command_tx.send(Action::NextScreen)?; - } - } - Action::SetMode(Mode::SelectDisks) => { - self.popup_text.clear(); - if let Some(command_tx) = self.command_tx.clone() { - command_tx.send(Action::UpdateDiskList(self.disks.clone()))?; - } - } + Action::SetMode(Mode::ScanDisks) => self.popup_text = String::from("Scanning Disks..."), _ => {} } Ok(None) diff --git a/src/components/right.rs b/src/components/right.rs index 15aa6fb..c0e9945 100644 --- a/src/components/right.rs +++ b/src/components/right.rs @@ -19,13 +19,14 @@ use ratatui::{prelude::*, widgets::*}; use tokio::sync::mpsc::UnboundedSender; use super::Component; -use crate::{action::Action, app::Mode, config::Config}; +use crate::{action::Action, app::Mode, config::Config, system::disk::Disk}; #[derive(Default)] pub struct Right { command_tx: Option>, config: Config, cur_mode: Mode, + disks: Vec, prev_mode: Mode, all_modes: Vec, selections: Vec>, @@ -76,6 +77,7 @@ impl Component for Right { self.cur_mode = new_mode; self.all_modes.push(new_mode); } + Action::UpdateDiskList(disks) => self.disks = disks, _ => {} } Ok(None) @@ -95,8 +97,12 @@ impl Component for Right { // Body let paragraph = Paragraph::new(format!( - "Prev Mode: {:?} // Cur Mode: {:?}\n{:?}\n{:?}", - self.prev_mode, self.cur_mode, self.all_modes, self.selections, + "Prev Mode: {:?} // Cur Mode: {:?}\n{:?}\n{:?}\nDisks: {}", + self.prev_mode, + self.cur_mode, + self.all_modes, + self.selections, + self.disks.len(), )) .block( Block::default() diff --git a/src/system/disk.rs b/src/system/disk.rs index f6ca11b..62d300d 100644 --- a/src/system/disk.rs +++ b/src/system/disk.rs @@ -135,7 +135,7 @@ impl fmt::Display for PartitionTableType { } pub fn get_disks() -> Vec { - let disks; + let disks: Vec; if cfg!(windows) { disks = diskpart::get_disks(); } else {