From 69c1ba8dbc40fce3835cb8bb2b81d70e34214cf5 Mon Sep 17 00:00:00 2001 From: Lutsai Aleksandr Date: Thu, 2 Jan 2025 02:31:43 +0300 Subject: [PATCH] Add size field, improve info, fix eject --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/drives.rs | 24 +++++++++++++++++++++++ src/main.rs | 5 +++-- src/tui.rs | 53 +++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b24cd46..d727bf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mmtui" -version = "0.1.0" +version = "0.1.1" dependencies = [ "crossterm", "ratatui", diff --git a/Cargo.toml b/Cargo.toml index b95b0ee..af5ef36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mmtui" -version = "0.1.0" +version = "0.1.1" edition = "2021" authors = ["Lutsai Aleksandr "] description = "Terminal User Interface disk mount manager for TUI file managers" diff --git a/src/drives.rs b/src/drives.rs index 2bf21a3..ba22254 100644 --- a/src/drives.rs +++ b/src/drives.rs @@ -4,11 +4,13 @@ use std::collections::HashMap; #[derive(Debug, Clone)] pub struct Block { pub object_path: String, + pub drive_path: String, pub dev: String, pub label: String, pub mount: Option, pub fstype: String, pub mounted: bool, + pub size: String, } #[derive(Debug, Clone)] @@ -56,8 +58,14 @@ pub async fn collect_drives_from_udisk() -> udisks2::Result> { } } else if let Ok(blk) = i.block().await { let drv_path = blk.drive().await?.to_string(); + let size = if let Ok(size) = blk.size().await { + client.size_for_display(size, true, false) + } else { + String::new() + }; let block = Block { object_path: path, + drive_path: drv_path.clone(), dev: String::from_utf8_lossy(&blk.device().await?) .chars() .filter(|c| c != &'\0') @@ -66,6 +74,7 @@ pub async fn collect_drives_from_udisk() -> udisks2::Result> { mount: None, fstype: blk.id_type().await?, mounted: false, + size, }; if let Some(d) = drives.iter_mut().find(|i| i.object_path == drv_path) { @@ -108,11 +117,13 @@ pub async fn collect_all() -> udisks2::Result> { } else { fstab.blocks.push(Block { object_path: String::new(), + drive_path: fstab.object_path.clone(), dev: i.dev, label: String::new(), mount: i.path, fstype: i.fs, mounted: i.mounted, + size: String::new(), }); } } @@ -151,3 +162,16 @@ pub async fn unmount(block: &Block) -> udisks2::Result<()> { Ok(()) } + +pub async fn eject(block: &Block) -> udisks2::Result<()> { + let client = udisks2::Client::new().await?; + + client + .object(block.drive_path.clone())? + .drive() + .await? + .eject(HashMap::new()) + .await?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index fa16a26..fcccedb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,9 @@ async fn main() -> udisks2::Result<()> { let s = state.clone(); tokio::spawn(async move { loop { - let drv = drives::collect_all().await.unwrap(); - s.lock().await.clone_from(&drv); + if let Ok(drv) = drives::collect_all().await { + s.lock().await.clone_from(&drv); + }; tokio::time::sleep(Duration::from_millis(500)).await; } }); diff --git a/src/tui.rs b/src/tui.rs index e7d5676..4bb3abd 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -24,7 +24,16 @@ pub struct Tui { pub last_status: String, } +const HELP: &str = "j/▲⋮k/▼⋮l/o/▶ - CD⋮m - Mount⋮u - Unmount⋮e - Eject⋮q - Quit"; + impl Tui { + fn set_status(&mut self, res: udisks2::Result<()>) { + self.last_status = match res { + Ok(()) => String::from("Ok"), + Err(e) => format!("Error: {e:?}"), + } + } + pub async fn input(&mut self, key: KeyEvent) -> InputResult { match key.code { KeyCode::Up | KeyCode::Char('k') => { @@ -37,21 +46,31 @@ impl Tui { } KeyCode::Char('m') => { if let Some(b) = &self.selected { - self.last_status = format!("{:?}", drives::mount(b).await); + self.set_status(drives::mount(b).await); } InputResult::None } KeyCode::Char('u') => { if let Some(b) = &self.selected { - self.last_status = format!("{:?}", drives::unmount(b).await); + self.set_status(drives::unmount(b).await); } InputResult::None } - KeyCode::Esc | KeyCode::Char('q') => InputResult::Quit, - KeyCode::Enter => { - let output = self.selected.clone().unwrap().mount.unwrap(); - InputResult::QuitChangeDirectory(output) + KeyCode::Char('e') => { + if let Some(b) = &self.selected { + self.set_status(drives::eject(b).await); + } + InputResult::None } + KeyCode::Enter | KeyCode::Char('l' | 'o') => { + if let Some(s) = &self.selected { + let output = s.clone().mount.unwrap_or_default(); + InputResult::QuitChangeDirectory(output) + } else { + InputResult::Quit + } + } + KeyCode::Esc | KeyCode::Char('q') => InputResult::Quit, _ => InputResult::None, } } @@ -81,11 +100,20 @@ impl Tui { .and_then(|n| rows.get(n).cloned()) .clone_into(&mut self.selected); + let max_size_field_length: u16 = rows + .iter() + .map(|r| r.size.len()) + .max() + .unwrap_or(0) + .try_into() + .unwrap_or(0); + let rows = rows.iter().map(|i| { Row::new(vec![ i.dev.clone(), i.label.clone(), i.mount.clone().unwrap_or_default(), + i.size.clone(), if i.mounted { "M".to_owned() } else { @@ -97,7 +125,8 @@ impl Tui { Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), - Constraint::Length(3), + Constraint::Length(max_size_field_length), + Constraint::Length(1), ]; let table = Table::new(rows, widths) .row_highlight_style(Color::Green) @@ -123,18 +152,14 @@ impl Tui { }; format!( - "dev: {:?} label: {:?} type: {:?} {mounted} ", - s.dev, s.label, s.fstype + "dev: {:?} label: {:?} type: {:?} size {} {mounted}", + s.dev, s.label, s.fstype, s.size ) } None => String::new(), }; - let info = format!( - "j - UP, k - DOWN, l - Goto mountpoint, m - Mount, u - Unmount, e - Eject\n{descr} {:?}", - self.last_status - ); - + let info = format!("{} | {HELP}\n{descr}", self.last_status); let info = Paragraph::new(info).wrap(Wrap { trim: true }); frame.render_widget(info, layout[1]); }